programowanieAnalityk Danych / Programista Backend

Jakie pułapki kryją się przy użyciu konstrukcji GROUP BY w SQL, szczególnie w kontekście agregacji i optymalizacji złożonych zapytań?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

GROUP BY służy do grupowania wierszy i agregowania danych, ale przy niewłaściwym zastosowaniu może powodować poważne błędy lub nieoptymalną pracę.

Kluczowe uwagi:

  • W SELECT dozwolone są tylko kolumny z GROUP BY lub funkcje agregujące.
  • W złożonych zapytaniach z wieloma JOINami mogą wystąpić duplikaty i nieprawidłowa agregacja.
  • Formalna kolejność: GROUP BY jest wykonywane po WHERE i przed HAVING.
  • W przypadku braku indeksowania kolumn grupujących zapytanie może działać bardzo wolno na dużych zbiorach danych.
  • HAVING filtruje już po grupowaniu, a WHERE — przed nim.

Przykład:

SELECT customer_id, COUNT(*) as orders FROM orders WHERE order_date >= '2024-01-01' GROUP BY customer_id HAVING COUNT(*) > 10;

Pytanie z haczykiem.

Czy w SELECT po GROUP BY można odwoływać się do pól, które nie były wskazane ani w GROUP BY, ani w funkcji agregującej?

Odpowiedź: Nie, to spowoduje błąd w większości realizacji SQL (np. w MS SQL, PostgreSQL). Niektóre specyficzne bazy danych mogą zwrócić losową, nieprawidłową wartość (szczególnie w MySQL, gdy sql_mode 'ONLY_FULL_GROUP_BY' jest wyłączony), ale takie zachowanie jest nieprawidłowe i nie jest gwarantowane przez standard. Prawidłowy przykład:

SELECT department, AVG(salary) FROM employees GROUP BY department;

Przykłady rzeczywistych błędów z powodu nieznajomości niuansów tematu.


Historia

W projekcie e-commerce raport "przychody z produktów" przygotowano zapytaniem SELECT sku, price, SUM(qty) FROM orders GROUP BY sku. Nie uwzględniono: price nie trafił do GROUP BY i był poza funkcją agregującą, wynik — MySQL zwrócił pierwszą napotkaną wartość ceny, co przy promocji spowodowało poważne błędy w raporcie. Poprawka — należy dodać price do GROUP BY lub użyć funkcji agregującej.


Historia

W projekcie BI złożony raport z wieloma JOIN i GROUP BY trwał 80 minut zamiast planowanych 3. Po analizie ustalono, że brakowało indeksów na polu z GROUP BY i filtrowaniu, tworzyły się ogromne tymczasowe tabele do agregacji. Rozwiązanie — optymalizacja indeksów i przepisanie zapytania z wykorzystaniem wyrażeń tabelarycznych.


Historia

Programista zastosował HAVING do filtrowania wartości według nieagregowanego atrybutu użytkownika. W rezultacie serwer wykonał grupowanie na wszystkich danych, a następnie usunął je zgodnie z HAVING, co obniżyło wydajność. Poprawiono — przeniesiono tę kontrolę do WHERE, aby zawęzić wybór przed agregacją.