Komentar awal
Harap pelajari cara menggunakan notasi JOIN eksplisit, bukan notasi gabung implisit lama (sebelum 1992).
Gaya lama:
SELECT transactionTable.rating as MostCommonRating
FROM personTable, transactionTable
WHERE personTable.transactionid = transactionTable.transactionid
AND personTable.personid = 1
GROUP BY transactionTable.rating
ORDER BY COUNT(transactionTable.rating) desc
LIMIT 1
Gaya yang disukai:
SELECT transactionTable.rating AS MostCommonRating
FROM personTable
JOIN transactionTable
ON personTable.transactionid = transactionTable.transactionid
WHERE personTable.personid = 1
GROUP BY transactionTable.rating
ORDER BY COUNT(transactionTable.rating) desc
LIMIT 1
Anda memerlukan kondisi AKTIF untuk setiap GABUNG.
Juga, personID
nilai dalam data adalah string, bukan angka, jadi Anda harus menulis
WHERE personTable.personid = "Ben"
misalnya, agar kueri berfungsi pada tabel yang ditampilkan.
Jawaban utama
Anda sedang mencari agregat dari sebuah agregat:dalam hal ini, jumlah maksimum. Jadi, solusi umum apa pun akan melibatkan MAX dan COUNT. Anda tidak dapat menerapkan MAX secara langsung ke COUNT, tetapi Anda dapat menerapkan MAX ke kolom dari sub-kueri yang kolomnya adalah COUNT.
Bangun kueri menggunakan Desain Kueri Berbasis Pengujian — TDQD.
Pilih orang dan peringkat transaksi
SELECT p.PersonID, t.Rating, t.TransactionID
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
Pilih orang, peringkat, dan jumlah kemunculan peringkat
SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
GROUP BY p.PersonID, t.Rating
Hasil ini akan menjadi sub-kueri.
Temukan berapa kali seseorang mendapat peringkat
SELECT s.PersonID, MAX(s.RatingCount)
FROM (SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
GROUP BY p.PersonID, t.Rating
) AS s
GROUP BY s.PersonID
Sekarang kita tahu berapa jumlah maksimum untuk setiap orang.
Hasil yang diperlukan
Untuk mendapatkan hasilnya, kita perlu memilih baris dari sub-query yang memiliki jumlah maksimum. Perhatikan bahwa jika seseorang memiliki 2 peringkat Baik dan 2 Buruk (dan 2 adalah jumlah maksimum peringkat dari jenis yang sama untuk orang tersebut), maka dua catatan akan ditampilkan untuk orang tersebut.
SELECT s.PersonID, s.Rating
FROM (SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
GROUP BY p.PersonID, t.Rating
) AS s
JOIN (SELECT s.PersonID, MAX(s.RatingCount) AS MaxRatingCount
FROM (SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
GROUP BY p.PersonID, t.Rating
) AS s
GROUP BY s.PersonID
) AS m
ON s.PersonID = m.PersonID AND s.RatingCount = m.MaxRatingCount
Jika Anda ingin jumlah peringkat yang sebenarnya juga, itu mudah dipilih.
Itu bagian SQL yang cukup kompleks. Saya akan benci untuk mencoba menulis itu dari awal. Memang, saya mungkin tidak akan repot; Saya akan mengembangkannya selangkah demi selangkah, kurang lebih seperti yang ditunjukkan. Namun karena kami telah men-debug sub-kueri sebelum menggunakannya dalam ekspresi yang lebih besar, kami dapat yakin dengan jawabannya.
DENGAN klausa
Perhatikan bahwa SQL Standar menyediakan klausa WITH yang mengawali pernyataan SELECT, menamai sub-kueri. (Ini juga dapat digunakan untuk kueri rekursif, tetapi kami tidak membutuhkannya di sini.)
WITH RatingList AS
(SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
GROUP BY p.PersonID, t.Rating
)
SELECT s.PersonID, s.Rating
FROM RatingList AS s
JOIN (SELECT s.PersonID, MAX(s.RatingCount) AS MaxRatingCount
FROM RatingList AS s
GROUP BY s.PersonID
) AS m
ON s.PersonID = m.PersonID AND s.RatingCount = m.MaxRatingCount
Ini lebih sederhana untuk ditulis. Sayangnya, MySQL belum mendukung klausa WITH.
SQL di atas sekarang telah diuji terhadap IBM Informix Dynamic Server 11.70.FC2 yang berjalan di Mac OS X 10.7.4. Tes itu mengungkap masalah yang didiagnosis dalam komentar awal. SQL untuk jawaban utama bekerja dengan benar tanpa perlu diubah.