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

MYSQL wyświetla nieprawidłowe wiersze podczas korzystania z funkcji GROUP BY

Jest to klasyczna przeszkoda, na którą wpada większość programistów MySQL.

  • Masz kolumnę ticket_id to jest argument GROUP BY . Odrębne wartości w tej kolumnie definiują grupy.
  • Masz kolumnę incoming_time to jest argument MAX() . Największa wartość w tej kolumnie nad wierszami w każdej grupie jest zwracana jako wartość MAX() .
  • Masz wszystkie inne kolumny artykułu tabeli. Wartości zwracane dla tych kolumn są dowolne, nie pochodzą z tego samego wiersza, w którym znajduje się MAX() pojawia się wartość.

Baza danych nie może wywnioskować, że chcesz wartości z tego samego wiersza, w którym występuje wartość maksymalna.

Pomyśl o następujących przypadkach:

  • Istnieje wiele wierszy, w których występuje ta sama wartość maksymalna. Który wiersz powinien być użyty do wyświetlenia kolumn article.* ?

  • Piszesz zapytanie, które zwraca zarówno MIN() i MAX() . Jest to legalne, ale który wiersz powinien article.* pokazać?

    SELECT article.* , MIN(article.incoming_time), MAX(article.incoming_time)
    FROM ticket, article
    WHERE ticket.id = article.ticket_id
    AND ticket.queue_id = 1
    GROUP BY article.ticket_id
    
  • Używasz funkcji agregującej, takiej jak AVG() lub SUM() , gdzie żaden wiersz nie ma tej wartości. W jaki sposób baza danych ma odgadnąć, który wiersz wyświetlić?

    SELECT article.* , AVG(article.incoming_time)
    FROM ticket, article
    WHERE ticket.id = article.ticket_id
    AND ticket.queue_id = 1
    GROUP BY article.ticket_id
    

W większości marek baz danych — a także w samym standardzie SQL — nie jest to dozwolone napisać takie zapytanie, z powodu niejednoznaczności. Na liście wyboru nie można uwzględnić żadnej kolumny, która nie znajduje się w funkcji agregującej ani nie ma nazwy w GROUP BY klauzula.

MySQL jest bardziej liberalny. Pozwala to zrobić i pozostawia tobie pisanie zapytań bez dwuznaczności. Jeśli masz niejednoznaczność, wybiera wartości z wiersza, który jest fizycznie pierwszy w grupie (ale to zależy od silnika pamięci).

Co jest warte, SQLite również zachowuje się tak, ale wybiera ostatni wiersz w grupie, aby rozwiązać niejednoznaczność. Domyśl. Jeśli standard SQL nie mówi, co robić, zależy to od implementacji dostawcy.

Oto zapytanie, które może rozwiązać Twój problem za Ciebie:

SELECT a1.* , a1.incoming_time AS maxtime
FROM ticket t JOIN article a1 ON (t.id = a1.ticket_id)
LEFT OUTER JOIN article a2 ON (t.id = a2.ticket_id 
  AND a1.incoming_time < a2.incoming_time)
WHERE t.queue_id = 1
  AND a2.ticket_id IS NULL;

Innymi słowy, poszukaj wiersza (a1 ), dla którego nie ma innego wiersza (a2 ) z tym samym ticket_id i większy incoming_time . Jeśli nie większy incoming_time zostanie znaleziony, LEFT OUTER JOIN zwraca NULL zamiast dopasowania.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dlaczego podczas łączenia się z MySQL za pomocą Javy (Netbeans) pojawia się błąd „Communications link Failure Ostatni wysłany pakiet...”?

  2. MySQL - aktualizowanie wszystkich rekordów w celu dopasowania maksymalnej wartości w grupie

  3. Dodać identyfikator automatycznego zwiększania do istniejącej tabeli?

  4. połącz dwie tabele wraz z liczbą rekordów z drugiej tabeli na podstawie warunku

  5. Session_start Szczegóły profilu użytkownika