最初に明確にすることは、SQLはMySQLではないということです。
標準SQLでは、集約されていないフィールドのサブセットでグループ化することは許可されていません。理由は非常に単純です。このクエリを実行していると仮定します:
SELECT color, owner_name, COUNT(*) FROM cars
GROUP BY color
そのクエリは意味がありません。説明しようとしても不可能です。確かにそれは色を選択し、色ごとの車の数を数えています。ただし、owner_name
も追加されています White
の場合のように、フィールドと特定の色の所有者が多数存在する可能性があります 色。したがって、owner_name
が多数存在する可能性がある場合 単一のcolor
の値 これはたまたまGROUP BY
の唯一のフィールドです 句...次に、どのowner_name
返されますか?
owner_name
を返す必要がある場合 次に、ある種の基準を追加して、そのうちの1つだけを選択する必要があります。たとえば、アルファベット順の最初の基準は、この場合はJohn
になります。 。その基準により、集計関数MIN(owner_name)
が追加されます。 そして、少なくともselectステートメントのすべての非集計フィールドによってグループ化されるため、クエリは再び意味をなします。
ご覧のとおり、標準SQLがグループ化に柔軟性を持たないことには明確で実用的な理由があります。そうでない場合は、列の値が予測できないという厄介な状況に直面する可能性があります。これは、特に実行中のクエリが銀行口座の取引を示している場合は、良い言葉ではありません。
そうは言っても、なぜMySQLは意味をなさないかもしれないクエリを許可するのでしょうか?さらに悪いことに、上記のクエリのエラーは構文的に検出される可能性があります。簡単な答えは、パフォーマンスです。長い答えは、データの関係に基づいて、グループから予測できない値を取得すると、予測可能な値になる特定の状況があるということです。
まだ理解していない場合、グループから予測できない要素を取得することで得られる値を予測できる唯一の方法は、グループ内のすべての要素が同じである場合です。この状況の明確な例は、まったく同じ質問のサンプルクエリにあります。 owner_id
がどのようになっているのか見てみましょう およびowner_name
表に関連します。 owner_id
が与えられた場合は明らかです 、例: 2
、1つの異なるowner_name
のみを持つことができます 。行数が多い場合でも、いずれかを選択すると、Mike
が得られます。 結果として。正式なデータベース用語では、これは owner_id
として説明できます。 owner_name
を機能的に決定します 。
完全に機能するMySQLクエリを詳しく見てみましょう:
SELECT owner_id, owner_name, COUNT(*) total FROM cars
GROUP BY owner_id
与えられたowner_id
これは同じowner_name
を返します 、GROUP BY
に追加します 句によって、それ以上の行が返されることはありません。集約された関数MAX(owner_name)
を追加することもできます 返される行が少なくなることはありません。結果のデータはまったく同じになります。どちらの場合も、少なくともすべての非集計フィールドがグループ化されるため、クエリはすぐに正当な標準SQLクエリに変換されます。したがって、同じ結果を得るには3つのアプローチがあります。
ただし、前述したように、この非標準のグループ化にはパフォーマンス上の利点があります。この
言及する価値のあることの1つは、結果が必ずしも間違っているというわけではないということです。 むしろ不確定 。言い換えれば、期待される結果が得られたからといって、正しいクエリを作成したとは限りません。適切なクエリを作成すると、常に期待どおりの結果が得られます。
ご覧のとおり、このMySQL拡張機能をGROUP BY
に適用する価値があるかもしれません。 句。とにかく、これがまだ100%明確でない場合は、グループ化が常に正しいことを確認する経験則があります。少なくとも、select句のすべての非集計フィールドで常にグループ化する 。特定の状況では数CPUサイクルを浪費している可能性がありますが、不確定を返すよりも優れています。 結果。それでも正しくグループ化できないことを恐れている場合は、 ONLY_FULL_GROUP_BY
SQLモードは最後の手段になる可能性があります:)
グループ化が正しく、パフォーマンスが高いように...または少なくとも正しいように。