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

GROUP BYを使用すると、MYSQLに誤った行が表示される

    これは、ほとんどのMySQLプログラマーが直面する古典的なハードルです。

    • ticket_idがあります これがGROUP BYへの引数です 。この列の個別の値は、グループを定義します。
    • 列がありますincoming_time これがMAX()への引数です 。各グループの行に対するこの列の最大値は、MAX()の値として返されます。 。
    • テーブル記事の他のすべての列があります。 これらの列に返される値は任意であり、MAX()と同じ行からではありません。 値が発生します。

    データベースは、最大値が発生するのと同じ行から値が必要であることを推測できません。

    次の場合について考えてください。

    • 同じ最大値が発生する複数の行があります。 article.*の列を表示するために使用する行 ?

    • MIN()の両方を返すクエリを記述します およびMAX() 。これは合法ですが、どの行をarticle.*にする必要があります 表示しますか?

      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
      
    • AVG()などの集計関数を使用します またはSUM() 、その値を持つ行はありません。データベースはどの行を表示するかをどのように推測しますか?

      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
      

    ほとんどのブランドのデータベース(およびSQL標準自体)では、許可されていません あいまいさのために、このようなクエリを作成します。集計関数内にない、またはGROUP BYで名前が付けられている列を、選択リストに含めることはできません。 条項。

    MySQLはより寛容です。これを行うことができ、あいまいさのないクエリを作成するのはあなたに任されています。あいまいな場合は、グループ内で物理的に最初の行から値を選択します(ただし、これはストレージエンジン次第です)。

    価値があるので、SQLiteにもこの動作がありますが、最後を選択します あいまいさを解決するためにグループ内の行。図に行きます。 SQL標準で何をすべきかが規定されていない場合は、ベンダーの実装次第です。

    問題を解決できるクエリは次のとおりです。

    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;
    

    つまり、行を探します(a1 )他の行がない(a2 )同じticket_idを使用 そしてより大きなincoming_time 。これ以上incoming_timeがない場合 が見つかった場合、LEFTOUTERJOINは一致ではなくNULLを返します。



    1. PL/SQLでのコールの並列化

    2. 年を保存するためのMySQLタイプ:SmallintまたはVarcharまたはDate?

    3. php password_verify()ハッシュとパスが一致しません

    4. 別のテーブルにレコードがないテーブルからレコードをフェッチする