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


26

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

  • Mais à quoi sert l'utilisation de la valeur numérique au lieu du nom de la colonne avec la clause Group by? Par exemple: Grouper par 1.

3
Utilisez order by 1uniquement lorsque vous êtes assis à l' mysql> invite. Dans le code, utilisez ORDER BY id ASC. Notez la casse, le nom de champ explicite et la direction de commande explicite.
dotancohen

Réponses:


28

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 un code beaucoup plus littéral.

Les raisons pour lesquelles c'est mauvais:

  • ce n'est pas de l'auto-documentation - 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 va se passer 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:


9

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

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 depuis ORDER BYet GROUP BYdepuis 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.


8

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. Le regroupement par date, servicesentraînerait Appset Applicationsserait considéré 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 Appspar l' Applicationsutilisation d'une CASEexpression ou de la IFfonction, puis à les regrouper sur les services en tant que:

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érés Appset en Applicationstant que services différents et donne le même résultat 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 des 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 la façon préférée d'écrire des requêtes, utilisez-la uniquement lorsque vous avez vraiment besoin de grouper sur une colonne aliasée.


" Mais cela regroupe toujours les services considérant les applications et applications comme des services différents et donne le même résultat que précédemment ". Cela ne serait-il pas résolu si vous avez choisi un nom différent (non conflictuel) pour l'alias?
Daddy32

3

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.


0

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

entrez la description de l'image ici


0
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:

regrouper par 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 aboutit à cette regrouper par 1,2,3

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.