Questo è un classico ostacolo che incontra la maggior parte dei programmatori MySQL.
- Hai una colonna
ticket_id
questo è l'argomento perGROUP BY
. Valori distinti in questa colonna definiscono i gruppi. - Hai una colonna
incoming_time
questo è l'argomento diMAX()
. Il valore massimo in questa colonna sulle righe di ciascun gruppo viene restituito come valore diMAX()
. - Hai tutte le altre colonne dell'articolo della tabella. I valori restituiti per queste colonne sono arbitrari, non dalla stessa riga in cui
MAX()
valore si verifica.
Il database non può dedurre che desideri valori dalla stessa riga in cui si verifica il valore massimo.
Pensa ai seguenti casi:
-
Sono presenti più righe in cui si verifica lo stesso valore massimo. Quale riga deve essere utilizzata per mostrare le colonne di
article.*
? -
Scrivi una query che restituisce sia
MIN()
e ilMAX()
. Questo è legale, ma quale riga dovrebbearticle.*
spettacolo?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
-
Utilizzi una funzione aggregata come
AVG()
oSUM()
, dove nessuna riga ha quel valore. Come fa il database a indovinare quale riga visualizzare?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
Nella maggior parte delle marche di database, così come nello stesso standard SQL, non sei autorizzato scrivere una query come questa, a causa dell'ambiguità. Non puoi includere alcuna colonna nell'elenco di selezione che non sia all'interno di una funzione di aggregazione o denominata in GROUP BY
clausola.
MySQL è più permissivo. Ti consente di farlo e lascia a te il compito di scrivere query senza ambiguità. In caso di ambiguità, seleziona i valori dalla riga che è fisicamente prima nel gruppo (ma dipende dal motore di archiviazione).
Per quel che vale, anche SQLite ha questo comportamento, ma sceglie l'ultimo fila nel gruppo per risolvere l'ambiguità. Vai a capire. Se lo standard SQL non dice cosa fare, dipende dall'implementazione del fornitore.
Ecco una domanda che può risolvere il tuo problema per te:
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;
In altre parole, cerca una riga (a1
) per cui non esiste un'altra riga (a2
) con lo stesso ticket_id
e un maggiore incoming_time
. Se non è superiore a incoming_time
viene trovato, il LEFT OUTER JOIN restituisce NULL invece di una corrispondenza.