10

編集: 私は MySQL を使用しています。同じ質問の別の投稿を見つけましたが、Postgres にあります。MySQL が必要です。

SQL の別の列の各値の最も一般的な値を取得する

このサイトや他のサイトを広範囲に検索した後、この質問をしますが、意図したとおりに機能する結果が見つかりませんでした.

人のテーブル (recordid、personid、transactionid) とトランザクション テーブル (transactionid、rating) があります。各人の最も一般的な評価を返す単一の SQL ステートメントが必要です。

現在、指定された人物 ID の最も一般的な評価を返すこの SQL ステートメントがあります。それは機能し、おそらく他の人を助けるかもしれません.

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

ただし、上記のステートメントが personTable の各 personid に対して行うことを行うステートメントが必要です。

私の試みは以下です。ただし、MySQL サーバーがタイムアウトします。

SELECT personid AS pid, 
(SELECT transactionTable.rating as MostCommonRating 
FROM personTable, transactionTable 
WHERE personTable.transactionid = transactionTable.transactionid 
AND personTable.personid = pid
GROUP BY transactionTable.rating 
ORDER BY COUNT(transactionTable.rating) desc 
LIMIT 1)
FROM persontable
GROUP BY personid

あなたが私に与えることができるどんな助けも大いに義務付けられます. ありがとう。

PERSONTABLE:

RecordID,   PersonID,   TransactionID
1,      Adam,       1
2,      Adam,       2
3,      Adam,       3
4,      Ben,        1
5,      Ben,        3
6,      Ben,        4
7,      Caitlin,    4
8,      Caitlin,    5
9,      Caitlin,    1

TRANSACTIONTABLE:

TransactionID,  Rating
1       Good
2       Bad
3       Good
4       Average
5       Average

私が探している SQL ステートメントの出力は次のようになります。

出力:

PersonID,   MostCommonRating
Adam        Good
Ben         Good
Caitlin     Average
4

3 に答える 3

27

予備コメント

古い (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 OS X 10.7.4 で実行されている IBM Informix Dynamic Server 11.70.FC2 に対してテストされています。そのテストにより、予備コメントで診断された問題が明らかになりました。主な回答の SQL は、変更する必要なく正しく機能しました。

于 2012-09-16T14:42:53.920 に答える