Ini adalah rintangan klasik yang dihadapi sebagian besar programmer MySQL.
- Anda memiliki kolom
ticket_id
itulah argumen untukGROUP BY
. Nilai yang berbeda dalam kolom ini menentukan grup. - Anda memiliki kolom
incoming_time
itu adalah argumen untukMAX()
. Nilai terbesar di kolom ini di atas baris di setiap grup dikembalikan sebagai nilaiMAX()
. - Anda memiliki semua kolom artikel tabel lainnya. Nilai yang dikembalikan untuk kolom ini bersifat arbitrer, bukan dari baris yang sama tempat
MAX()
nilai terjadi.
Basis data tidak dapat menyimpulkan bahwa Anda menginginkan nilai dari baris yang sama tempat nilai maksimum muncul.
Pikirkan tentang kasus berikut:
-
Ada beberapa baris di mana nilai maks yang sama muncul. Baris mana yang harus digunakan untuk menampilkan kolom
article.*
? -
Anda menulis kueri yang mengembalikan
MIN()
danMAX()
. Ini legal, tetapi baris mana yang harusarticle.*
tampilkan?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
-
Anda menggunakan fungsi agregat seperti
AVG()
atauSUM()
, di mana tidak ada baris yang memiliki nilai tersebut. Bagaimana database menebak baris mana yang akan ditampilkan?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
Di sebagian besar merek basis data -- serta standar SQL itu sendiri -- Anda tidak diizinkan untuk menulis kueri seperti ini, karena ambiguitas. Anda tidak dapat menyertakan kolom apa pun dalam daftar pilih yang tidak ada di dalam fungsi agregat atau diberi nama di GROUP BY
klausa.
MySQL lebih permisif. Ini memungkinkan Anda melakukan ini, dan membiarkan Anda menulis kueri tanpa ambiguitas. Jika Anda memiliki ambiguitas, ini akan memilih nilai dari baris yang secara fisik berada di urutan pertama dalam grup (tetapi ini tergantung pada mesin penyimpanan).
Untuk apa nilainya, SQLite juga memiliki perilaku ini, tetapi memilih terakhir baris dalam kelompok untuk menyelesaikan ambiguitas. pergilah. Jika standar SQL tidak mengatakan apa yang harus dilakukan, itu terserah implementasi vendor.
Berikut pertanyaan yang dapat memecahkan masalah Anda:
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;
Dengan kata lain, cari baris (a1
) yang tidak memiliki baris lain (a2
) dengan ticket_id
yang sama dan incoming_time
. yang lebih besar . Jika tidak ada incoming_time
. yang lebih besar ditemukan, LEFT OUTER JOIN mengembalikan NULL alih-alih kecocokan.