Dit is een klassieke hindernis waar de meeste MySQL-programmeurs tegenaan lopen.
- Je hebt een kolom
ticket_id
dat is het argument voorGROUP BY
. Verschillende waarden in deze kolom definiëren de groepen. - Je hebt een kolom
incoming_time
dat is het argument voorMAX()
. De grootste waarde in deze kolom over de rijen in elke groep wordt geretourneerd als de waarde vanMAX()
. - Je hebt alle andere kolommen met tabelartikel. De geretourneerde waarden voor deze kolommen zijn willekeurig, niet van dezelfde rij waar de
MAX()
waarde komt voor.
De database kan niet afleiden dat u waarden wilt uit dezelfde rij waar de maximale waarde voorkomt.
Denk aan de volgende gevallen:
-
Er zijn meerdere rijen waar dezelfde maximale waarde voorkomt. Welke rij moet worden gebruikt om de kolommen van
article.*
. weer te geven ? -
U schrijft een query die zowel de
MIN()
en deMAX()
. Dit is legaal, maar welke rij moetarticle.*
laten zien?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 gebruikt een verzamelfunctie zoals
AVG()
ofSUM()
, waarbij geen enkele rij die waarde heeft. Hoe moet de database raden welke rij moet worden weergegeven?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 de meeste databasemerken -- evenals de SQL-standaard zelf -- is het niet toegestaan om een query als deze te schrijven, vanwege de dubbelzinnigheid. U kunt geen kolommen in de selectielijst opnemen die niet in een statistische functie staan of die niet in de GROUP BY
staan. clausule.
MySQL is toleranter. Het laat u dit doen en laat het aan u over om vragen te schrijven zonder dubbelzinnigheid. Als je dubbelzinnigheid hebt, selecteert het waarden uit de rij die fysiek als eerste in de groep staat (maar dit is aan de opslagengine).
Voor wat het waard is, SQLite heeft ook dit gedrag, maar het kiest de laatste rij in de groep om de dubbelzinnigheid op te lossen. Ga figuur. Als de SQL-standaard niet zegt wat te doen, ligt het aan de implementatie van de leverancier.
Hier is een vraag die uw probleem voor u kan oplossen:
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;
Met andere woorden, zoek naar een rij (a1
) waarvoor er geen andere rij is (a2
) met dezelfde ticket_id
en een grotere incoming_time
. Indien geen grotere incoming_time
wordt gevonden, retourneert de LEFT OUTER JOIN NULL in plaats van een overeenkomst.