web-dev-qa-db-fra.com

Pourquoi utilisons-nous Group by 1 et Group by 1,2,3 dans une requête SQL?

Dans les requêtes SQL, nous utilisons la clause Group by pour appliquer des fonctions d'agrégation.

  • Mais quel est le but derrière l'utilisation de la valeur numérique au lieu du nom de la colonne avec la clause Group by? Par exemple: Grouper par 1.
28
ursitesion

C'est en fait une très mauvaise chose à faire à mon humble avis, et ce n'est pas pris en charge dans la plupart des autres plates-formes de bases de données.

Les raisons pour lesquelles les gens le font:

  • ils sont paresseux - Je ne sais pas pourquoi les gens pensent que leur productivité est améliorée en écrivant du code laconique plutôt qu'en tapant pendant 40 millisecondes supplémentaires pour obtenir beaucoup code plus littéral.

Les raisons pour lesquelles c'est mauvais:

  • ce n'est pas auto-documenté - quelqu'un va devoir analyser la liste SELECT pour comprendre le regroupement. Ce serait en fait un peu plus clair dans SQL Server, qui ne prend pas en charge le regroupement cowboy qui sait ce qui se passera comme le fait MySQL.

  • c'est fragile - quelqu'un entre et modifie la liste SELECT parce que les utilisateurs professionnels voulaient une sortie de rapport différente, et maintenant votre sortie est un gâchis. Si vous aviez utilisé des noms de colonne dans le GROUP BY, l'ordre dans la liste SELECT ne serait pas pertinent.

SQL Server prend en charge ORDER BY [ordinal]; voici quelques arguments parallèles contre son utilisation:

30
Aaron Bertrand

MySQL vous permet de faire GROUP BY avec des alias ( Problèmes avec les alias de colonne ). Ce serait bien mieux que de faire GROUP BY avec des nombres.

Google a de nombreux exemples d'utilisation et pourquoi beaucoup ont cessé de l'utiliser.

Pour être honnête avec vous, je n'ai pas utilisé de numéros de colonne pour ORDER BY et GROUP BY depuis 1996 (je faisais du développement Oracle PL/SQL à l'époque). L'utilisation des numéros de colonne est vraiment pour les anciens et la compatibilité descendante permet à ces développeurs d'utiliser MySQL et d'autres SGBDR qui le permettent encore.

9
RolandoMySQLDBA

Considérez le cas ci-dessous:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Apps         |         1 |
| 2016-05-31 | Applications |         1 |
| 2016-05-31 | Applications |         1 |
| 2016-05-31 | Apps         |         1 |
| 2016-05-31 | Videos       |         1 |
| 2016-05-31 | Videos       |         1 |
| 2016-06-01 | Apps         |         3 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Videos       |         2 |
| 2016-06-01 | Apps         |         2 |
+------------+--------------+-----------+

Vous devez connaître le nombre de téléchargements par service et par jour en considérant les applications et applications comme le même service. Regroupement par date, services entraînerait que Apps et Applications seraient considérés comme des services distincts.

Dans ce cas, la requête serait:

 select date, services, sum(downloads) as downloads
 from test.zvijay_test
 group by date,services

Et sortie:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Apps         |         2 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Apps         |         5 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

Mais ce n'est pas ce que vous voulez, car les applications et les applications à regrouper sont obligatoires. Alors, que pouvons-nous faire?

Une façon consiste à remplacer Apps par Applications en utilisant une expression CASE ou la fonction IF, puis en les regroupant sur les services comme suit:

select 
  date,
  if(services='Apps','Applications',services) as services,
  sum(downloads) as downloads
from test.zvijay_test 
group by date,services

Mais cela regroupe toujours les services considérant Apps et Applications comme des services différents et donne la même sortie que précédemment:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Applications |         5 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

Le regroupement sur un numéro de colonne vous permet de regrouper les données sur une colonne aliasée.

select
  date,
  if(services='Apps','Applications',services) as services,
  sum(downloads) as downloads
from test.zvijay_test
group by date,2;

Et vous donnant ainsi la sortie souhaitée comme ci-dessous:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         4 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         9 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

J'ai lu à plusieurs reprises que c'est une façon paresseuse d'écrire des requêtes ou de regrouper sur une colonne aliasée ne fonctionne pas dans MySQL, mais c'est la façon de regrouper sur des colonnes aliasées.

Ce n'est pas le moyen préféré d'écrire des requêtes, utilisez-le uniquement lorsque vous avez vraiment besoin de grouper sur une colonne aliasée.

8
imVJ

Il n'y a aucune raison valable de l'utiliser. Il s'agit simplement d'un raccourci paresseux spécialement conçu pour rendre difficile pour un développeur pressé de comprendre votre regroupement ou tri plus tard ou pour permettre au code d'échouer lamentablement lorsque quelqu'un change l'ordre des colonnes. Soyez attentif à vos collègues développeurs et ne le faites pas.

3
BriteSponge

Cela fonctionne pour moi. Le code regroupe les lignes jusqu'à 5 groupes.

SELECT
USR.UID,
USR.PROFILENAME,
(
    CASE 
    WHEN MOD(@curRow, 5) = 0 AND @curRow > 0 THEN
        @curRow := 0
    ELSE
        @curRow := @curRow + 1 
        /*@curRow := 1*/ /*AND @curCode := USR.UID*/
    END
) AS sort_by_total  
FROM
    SS_USR_USERS USR,
    (
        SELECT
            @curRow := 0,
            @curCode := ''
    ) rt
ORDER BY
    USR.PROFILENAME,
    USR.UID

Le résultat sera le suivant

enter image description here

SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2;

SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2,3;

Considérez les requêtes ci-dessus: Grouper par 1 signifie grouper par la première colonne et grouper par 1,2 signifie grouper par la première et la deuxième colonne et grouper par 1,2,3 signifie grouper par la première deuxième et la troisième colonne. Par exemple:

group by 1,2

cette image montre les deux premières colonnes groupées par 1,2 c'est-à-dire qu'elle ne prend pas en compte les différentes valeurs de dep_date pour trouver le compte (pour calculer le compte, toutes les combinaisons distinctes des deux premières colonnes sont prises en considération) tandis que la deuxième requête en résulte - group by 1,2,3

image. Ici, il considère les trois premières colonnes et il existe différentes valeurs pour trouver le nombre, c'est-à-dire qu'il est regroupé par les trois premières colonnes (pour calculer le nombre, toutes les combinaisons distinctes des trois premières colonnes sont prises en considération).

0
coder