予備コメント
古い(1992年以前の)暗黙的な結合表記ではなく、明示的なJOIN表記の使用方法を学習してください。
古いスタイル:
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
好みのスタイル:
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
JOINごとにON条件が必要です。
また、personID
データの値は数値ではなく文字列であるため、書き込む必要があります
WHERE personTable.personid = "Ben"
たとえば、表示されているテーブルでクエリを機能させるには。
主な答え
アグリゲートのアグリゲートを検索しようとしています。この場合は、カウントの最大値です。したがって、一般的なソリューションには、MAXとCOUNTの両方が含まれます。 MAXをCOUNTに直接適用することはできませんが、列がCOUNTであるサブクエリから列にMAXを適用することはできます。
テスト駆動クエリ設計—TDQDを使用してクエリを構築します。
人と取引の評価を選択
SELECT p.PersonID, t.Rating, t.TransactionID
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
人物、評価、評価の発生回数を選択
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, 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
これで、各人の最大数がわかりました。
必要な結果
結果を取得するには、サブクエリから最大数の行を選択する必要があります。誰かが2つの良い評価と2つの悪い評価を持っている場合(そして2はその人の同じタイプの評価の最大数です)、その人の2つのレコードが表示されることに注意してください。
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
実際の評価数も必要な場合は、簡単に選択できます。
これはかなり複雑なSQLです。ゼロから書いてみたくありません。確かに、私はおそらく気にしないでしょう。示されているように、多かれ少なかれ段階的に開発します。ただし、サブクエリをより大きな式で使用する前にデバッグしたので、答えに自信を持つことができます。
WITH句
標準SQLには、サブクエリに名前を付けてSELECTステートメントの前に付けるWITH句が用意されていることに注意してください。 (再帰クエリにも使用できますが、ここでは必要ありません。)
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
これは書くのが簡単です。残念ながら、MySQLはまだWITH句をサポートしていません。
上記のSQLは、Mac OSX10.7.4で実行されているIBMInformixDynamicServer11.70.FC2に対してテストされています。そのテストは、予備的なコメントで診断された問題を明らかにしました。メインアンサーのSQLは、変更することなく正しく機能しました。