Dlaczego używamy Grupuj według 1 i Grupuj według 1,2,3 w zapytaniu SQL?

26

W zapytaniach SQL używamy funkcji Grupuj według, aby zastosować funkcje agregujące.

  • Ale po co używać wartości liczbowej zamiast nazwy kolumny w Grupuj według klauzuli? Na przykład: Grupuj według 1.
strona internetowa
źródło
3
Używaj order by 1tylko, gdy siedzisz przy mysql> monicie. W kodzie użyj ORDER BY id ASC. Zanotuj przypadek, wyraźną nazwę pola i wyraźny kierunek zamawiania.
dotancohen,

Odpowiedzi:

28

Jest to naprawdę zła rzecz do zrobienia IMHO i nie jest obsługiwana na większości innych platform baz danych.

Powody, dla których ludzie to robią:

  • są leniwi - nie wiem, dlaczego ludzie uważają, że ich wydajność poprawia się, pisząc zwięzły kod, zamiast pisać przez dodatkowe 40 milisekund, aby uzyskać znacznie bardziej dosłowny kod.

Powody, dla których jest zły:

  • nie jest to samo-dokumentowanie - ktoś będzie musiał przeanalizować listę WYBIERZ, aby dowiedzieć się o grupowaniu. W SQL Server byłoby to nieco bardziej przejrzyste, które nie obsługuje grupowania kowbojów, którzy wiedzą, co się stanie, tak jak MySQL.

  • jest kruchy - ktoś wchodzi i zmienia listę WYBIERZ, ponieważ użytkownicy biznesowi chcieli innego wyjścia raportu, a teraz twój bałagan. Jeśli użyłeś nazw kolumn w GROUP BY, kolejność na liście WYBIERZ byłaby nieistotna.

SQL Server obsługuje ORDER BY [porządkowy]; oto kilka równoległych argumentów przeciwko jego użyciu:

Aaron Bertrand
źródło
9

MySQL pozwala robić GROUP BYaliasy ( problemy z aliasami kolumn ). Byłoby to znacznie lepsze niż w GROUP BYprzypadku liczb.

Google ma wiele przykładów użycia tego i dlaczego wielu przestało go używać.

Aby być z tobą szczery, nie użyłem liczby kolumn do ORDER BYi GROUP BYod 1996 roku (robiłem Oracle PL / SQL Development w czasie). Używanie numerów kolumn jest tak naprawdę dla starych timerów, a kompatybilność wsteczna pozwala takim programistom korzystać z MySQL i innych RDBMS, które wciąż na to pozwalają.

RolandoMySQLDBA
źródło
8

Rozważ poniższy przypadek:

+------------+--------------+-----------+
| 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 |
+------------+--------------+-----------+

Musisz sprawdzić liczbę pobrań na usługę dziennie, biorąc pod uwagę aplikacje i aplikacje jako tę samą usługę. Grupowanie przez date, servicesskutkowałoby Appsi Applicationssą traktowane jako oddzielne usługi.

W takim przypadku zapytaniem byłoby:

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

I wyjście:

+------------+--------------+-----------+
| 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 |
+------------+--------------+-----------+

Ale to nie jest to, czego chcesz, ponieważ aplikacje i aplikacje muszą być pogrupowane. Więc co możemy zrobić?

Jednym ze sposobów jest wymiana Appsz Applicationsużyciem CASEwyrażenia lub IFfunkcji, a następnie grupowanie ich w usługi jak:

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

Ale nadal grupuje usługi rozważające Appsi Applicationsjako różne usługi i daje taką samą wydajność jak poprzednio:

+------------+--------------+-----------+
| 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 |
+------------+--------------+-----------+

Grupowanie według numeru kolumny umożliwia grupowanie danych w kolumnie aliasowanej.

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

W ten sposób uzyskujesz pożądaną wydajność, jak poniżej:

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

Czytałem wiele razy, że jest to leniwy sposób pisania zapytań lub grupowania według kolumny aliasowanej, nie działa w MySQL, ale jest to sposób grupowania według kolumn aliasowanych.

To nie jest preferowany sposób pisania zapytań, używaj go tylko wtedy, gdy naprawdę musisz pogrupować kolumnę aliasu.

imVJ
źródło
Ale nadal grupuje usługi, traktując aplikacje i aplikacje jako różne usługi i daje takie same wyniki jak poprzednio ”. Czy nie da się tego rozwiązać, jeśli wybierzesz inną (nie powodującą konfliktu) nazwę dla aliasu?
Daddy32
3

Nie ma ważnego powodu, aby z niego korzystać. Jest to po prostu leniwy skrót specjalnie zaprojektowany, aby utrudnić niektórym trudnym programistom późniejsze ustalenie grupowania lub sortowania lub pozwolić, aby kod nie powiódł się źle, gdy ktoś zmieni kolejność kolumn. Uważaj na innych programistów i nie rób tego.

BriteSponge
źródło
0

To działa dla mnie. Kod grupuje wiersze do 5 grup.

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

Wynik będzie następujący

wprowadź opis zdjęcia tutaj

ship shuk - www.shipshuk.com
źródło
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;

Rozważ powyższe zapytania: Grupuj według 1 środka, aby pogrupować według pierwszej kolumny i grupuj według 1,2 środka, aby pogrupować według pierwszej i drugiej kolumny i grupuj według 1,2,3 sposobu, aby pogrupować według pierwszej drugiej i trzeciej kolumny. Na przykład:

pogrupuj według 1,2

ten obraz pokazuje pierwsze dwie kolumny pogrupowane według 1,2, tj. nie uwzględnia różnych wartości dep_date w celu znalezienia liczby (do obliczenia liczby brane są pod uwagę wszystkie odrębne kombinacje pierwszych dwóch kolumn), podczas gdy drugie zapytanie daje wynik pogrupuj według 1,2,3

obraz. Tutaj bierze się pod uwagę wszystkie pierwsze trzy kolumny i istnieją różne wartości, aby znaleźć liczbę, tj. Grupuje się według wszystkich pierwszych trzech kolumn (aby obliczyć liczbę, brane są pod uwagę wszystkie odrębne kombinacje pierwszych trzech kolumn).

koder
źródło