SQL Server UNION - デフォルトの ORDER BY 動作とは何ですか
-
05-07-2019 - |
質問
不自然な例として、いくつかの UNION ステートメントがあるとします。
SELECT * FROM xxx WHERE z = 1
UNION
SELECT * FROM xxx WHERE z = 2
UNION
SELECT * FROM xxx WHERE z = 3
デフォルトとは何ですか order by
行動?
私が見ているテストデータは基本的に、上で指定した順序でデータを返しません。つまり、データは順序付けされていますが、これに関する優先規則は何なのかを知りたかったのです。
もう 1 つは、この場合 xxx は View であるということです。このビューは 3 つの異なるテーブルを結合して、必要な結果を返します。
解決
デフォルトの順序はありません。
Order By 句がない場合、返される順序は未定義です。つまり、SQL Serverは好きな順序でそれらを戻すことができます。
編集: 私が見たものに基づいて、Order Byなしで、結果が返される順序はクエリプランによって異なります。そのため、使用しているインデックスがある場合、結果はその順序で返されますが、保証はありません。
他のヒント
ORDER BY句の追加に関して:
これはおそらくここで最も基本的なことですが、これを追加すると思いました。 結果を混在させたくない場合があります。そのため、最初のクエリの結果、2番目のクエリの結果などが必要になります。それを行うには、ダミーの最初の列を追加し、それで並べ替えます。ユニオンの列のエイリアスを忘れると問題が発生する可能性があるため、通常、列名ではなく順序句で順序を使用します。
例:
SELECT 1, * FROM xxx WHERE z = 'abc'
UNION ALL
SELECT 2, * FROM xxx WHERE z = 'def'
UNION ALL
SELECT 3, * FROM xxx WHERE z = 'ghi'
ORDER BY 1
ダミーの序数列は、2つのクエリを実行し、1つだけが結果を返すことがわかっている場合にも役立ちます。その後、返された結果の序数を確認するだけです。これにより、複数のデータベース呼び出しとほとんど空の結果セットのチェックを行う必要がなくなります。
実際の答えが見つかりました。
UNIONは重複を削除するため、DISTINCT SORTを実行します。これは、すべてのUNIONステートメントが連結される前に実行されます(実行計画を確認してください)。
ソートを停止するには、UNION ALLを実行します。これにより重複も削除されません。
レコードが返される順序を気にする場合は、順序を使用する必要があります。
除外すると、(クエリプランで選択されたインデックスに基づいて)整理される可能性がありますが、今日表示される結果は期待した結果ではなく、明日同じクエリが実行されるときに変更します。
編集:適切で具体的な例:(すべての例はMS SQLサーバーです)
-
Dave Pinalのブログでは、異なるインデックスが使用されているため、2つの非常に類似したクエリが異なる見かけの順序を表示する方法について説明しています。
SELECT ContactID FROM Person.Contact SELECT * FROM Person.Contact
-
Conor Cunningham は、テーブルが大きくなったときに見かけの順序がどのように変化するかを示しています(クエリオプティマイザーが並列実行プランを使用することを決定した場合)。
-
Hugo Kornelis 見かけの順序が常に主キーに基づいているとは限らないことを証明します。 ここに説明付きのフォローアップ投稿があります。
UNIONは、結果セットの順序に関して不正な場合があります。データベースは、UNIONで暗黙的なDISTINCTを提供するソートメソッドを時々使用するためです。もちろん、暗黙の明確な区別がないUNION ALLに。
ただし、10g +のOracleのハッシュメソッドなど、順序が適用されない暗黙の個別のアルゴリズムがあります。
DJが言うように、常にORDER BYを使用します
テーブルデータが挿入順序で返されることを前提とする不十分に記述されたコードに出くわすことは非常に一般的です。 、Oracle、MySQL)。もちろん、これは完全な誤acyであり、発生した場合は常に修正する必要があります。常に例外なく、自分でOrder By句を使用してください。
私の実際の経験から、「UNION ALL」に対して「UNION」を使用することで順序を変更できます...あなたのクエリが似ている場合、つまり
Select Count(*) from Table A
UNION
Select Count(*) from Table B
result is
10
26
「UNION」を「UNION ALL」に置き換えることで順序を入れ替えることができます...結果は次のようになります
26
10