sql >> データベース >  >> RDS >> Mysql

SQL:各人に最も一般的な値を返す

    予備コメント

    古い(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は、変更することなく正しく機能しました。



    1. 照合の不正な組み合わせMySQLエラー

    2. DATABASE()–MySQLで現在のデータベース名を取得します

    3. MySQL#1093-FROM句で更新するターゲットテーブル「giveaways」を指定できません

    4. PostgreSQLを使用する1つのエンティティ用の複数のHibernateシーケンスジェネレータ