Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak poprawnie GROUP BY w MySQL?

Pierwszą rzeczą, którą należy wyjaśnić, jest to, że SQL to nie MySQL.

W standardowym SQL nie jest dozwolone grupowanie według podzbioru pól niezagregowanych. Powód jest bardzo prosty. Załóżmy, że uruchamiam to zapytanie:

SELECT color, owner_name, COUNT(*) FROM cars
GROUP BY color

To zapytanie nie miałoby sensu. Nawet próba wyjaśnienia byłaby niemożliwa. Na pewno jest to wybór kolorów i liczenie ilości samochodów na kolor. Jednak dodaje również owner_name pola i może być wielu właścicieli dla danego koloru, tak jak w przypadku White kolor. Więc jeśli może być wiele owner_name wartości dla pojedynczego color które jest jedynym polem w GROUP BY klauzula... to która owner_name zostanie zwrócony?

Jeśli konieczne jest zwrócenie owner_name wtedy należy dodać jakieś kryteria, aby wybrać tylko jedno z nich, np. pierwsze z nich alfabetycznie, czyli w tym przypadku będzie to John . To kryterium spowoduje dodanie funkcji agregującej MIN(owner_name) a wtedy zapytanie znów nabierze sensu, ponieważ będzie grupować przynajmniej wszystkie niezagregowane pola w instrukcji select.

Jak widać, istnieje jasny i praktyczny powód, dla którego standardowy SQL jest nieelastyczny w grupowaniu. Gdyby tak nie było, możesz napotkać niezręczne sytuacje, w których wartość kolumny będzie nieprzewidywalna, a to nie jest miłe słowo, szczególnie jeśli uruchamiane zapytanie pokazuje transakcje na Twoim koncie bankowym.

Powiedziawszy to, dlaczego MySQL miałby zezwalać na zapytania, które mogą nie mieć sensu? A co gorsza, błąd w powyższym zapytaniu mógłby zostać po prostu wykryty składniowo! Krótka odpowiedź brzmi:wydajność. Długa odpowiedź brzmi, że istnieją pewne sytuacje, w których na podstawie relacji danych otrzymanie nieprzewidywalnej wartości z grupy da w wyniku przewidywalną wartość.

Jeśli jeszcze tego nie rozgryzłeś, jedynym sposobem, w jaki możesz przewidzieć wartość, jaką uzyskasz z pobrania nieprzewidywalnego elementu z grupy, będzie stwierdzenie, że wszystkie elementy w grupie są takie same. Jasnym przykładem tej sytuacji jest przykładowe zapytanie w tym samym pytaniu. Zobacz, jak owner_id i owner_name odnosi się do tabeli. Oczywiste jest, że podano dowolny owner_id , np. 2 , możesz mieć tylko jedną odrębną owner_name . Nawet mając wiele wierszy, wybierając dowolny, otrzymasz Mike jako wynik. W formalnym żargonie bazy danych można to wyjaśnić jako owner_id funkcjonalnie określa owner_name .

Przyjrzyjmy się bliżej temu w pełni działającemu zapytaniu MySQL:

SELECT owner_id, owner_name, COUNT(*) total FROM cars
GROUP BY owner_id

Podano dowolny owner_id to zwróciłoby to samo owner_name , więc dodanie go do GROUP BY klauzula nie spowoduje zwrócenia większej liczby wierszy. Nawet dodanie zagregowanej funkcji MAX(owner_name) nie spowoduje zwrócenia mniejszej liczby wierszy. Otrzymane dane będą dokładnie takie same. W obu przypadkach zapytanie zostałoby natychmiast przekształcone w legalne standardowe zapytanie SQL, ponieważ przynajmniej wszystkie pola niezagregowane zostałyby pogrupowane według. Istnieją więc 3 podejścia do uzyskania tych samych wyników.

Jednak, jak wspomniałem wcześniej, to niestandardowe grupowanie ma przewagę wydajnościową. Możesz sprawdzić ten tak niedoceniany link w którym jest to wyjaśnione bardziej szczegółowo, ale zamierzam przytoczyć najważniejszą część:

Warto wspomnieć, że wyniki niekoniecznie są złe ale raczej nieokreślony . Innymi słowy, uzyskanie oczekiwanych wyników nie oznacza, że ​​napisałeś właściwe zapytanie. Napisanie właściwego zapytania zawsze da oczekiwane rezultaty.

Jak widać, warto zastosować to rozszerzenie MySQL do GROUP BY klauzula. W każdym razie, jeśli nie jest to jeszcze w 100% jasne, istnieje praktyczna zasada, która zapewni, że grupowanie będzie zawsze poprawne:Zawsze grupuj przynajmniej według wszystkich niezagregowanych pól w klauzuli select . W pewnych sytuacjach możesz marnować kilka cykli procesora, ale jest to lepsze niż zwracanie nieokreślonego wyniki. Jeśli nadal boisz się nieprawidłowego grupowania, zmień ONLY_FULL_GROUP_BY Tryb SQL może być ostatecznością :)

Oby Twoje grupowanie było poprawne i wydajne... a przynajmniej poprawne.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Korzystanie z bazy danych NoSQL przez MySQL

  2. Jaka jest różnica między typami danych kolumn MySQL BOOL i BOOLEAN?

  3. Mysql Wybierz różne rekordy tylko z ostatnich dat

  4. mysql automatycznie przesyła ciągi do liczby całkowitej

  5. Json koduje cały zestaw wyników mysql