Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MYSQL zeigt bei Verwendung von GROUP BY falsche Zeilen an

Dies ist eine klassische Hürde, auf die die meisten MySQL-Programmierer stoßen.

  • Sie haben eine Spalte ticket_id das ist das Argument für GROUP BY . Eindeutige Werte in dieser Spalte definieren die Gruppen.
  • Sie haben eine Spalte incoming_time das ist das Argument für MAX() . Der größte Wert in dieser Spalte über die Zeilen in jeder Gruppe wird als Wert von MAX() zurückgegeben .
  • Sie haben alle anderen Spalten der Tabelle Artikel. Die für diese Spalten zurückgegebenen Werte sind willkürlich und stammen nicht aus derselben Zeile wie MAX() Wert auftritt.

Die Datenbank kann nicht ableiten, dass Sie Werte aus derselben Zeile wünschen, in der der Maximalwert auftritt.

Denken Sie an die folgenden Fälle:

  • Es gibt mehrere Zeilen, in denen derselbe Maximalwert auftritt. Welche Zeile soll verwendet werden, um die Spalten von article.* anzuzeigen ?

  • Sie schreiben eine Abfrage, die sowohl MIN() zurückgibt und das MAX() . Dies ist zulässig, aber welche Zeile sollte article.* sein anzeigen?

    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
    
  • Sie verwenden eine Aggregatfunktion wie AVG() oder SUM() , wobei keine Zeile diesen Wert hat. Wie soll die Datenbank erraten, welche Zeile angezeigt werden soll?

    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
    

In den meisten Datenbankmarken – ebenso wie im SQL-Standard selbst – sind Sie nicht erlaubt eine Abfrage wie diese zu schreiben, wegen der Mehrdeutigkeit. Sie können keine Spalte in die Auswahlliste aufnehmen, die sich nicht in einer Aggregatfunktion befindet oder in GROUP BY benannt ist Klausel.

MySQL ist freizügiger. Es lässt Sie dies tun und überlässt es Ihnen, Abfragen ohne Mehrdeutigkeit zu schreiben. Wenn Sie Mehrdeutigkeit haben, werden Werte aus der Zeile ausgewählt, die physisch an erster Stelle in der Gruppe steht (dies liegt jedoch an der Speicher-Engine).

Für das, was es wert ist, hat SQLite auch dieses Verhalten, aber es wählt das letzte Zeile in der Gruppe, um die Mehrdeutigkeit aufzulösen. Stelle dir das vor. Wenn der SQL-Standard nicht vorschreibt, was zu tun ist, liegt es an der Herstellerimplementierung.

Hier ist eine Abfrage, die Ihr Problem für Sie lösen kann:

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;

Suchen Sie also nach einer Zeile (a1 ), für die es keine andere Zeile gibt (a2 ) mit derselben ticket_id und eine größere incoming_time . Wenn nicht größer incoming_time gefunden wird, gibt der LEFT OUTER JOIN NULL statt einer Übereinstimmung zurück.