NULLが最初にソートされるのはなぜですか?


20

列にNULL値があり、値の昇順で並べ替えるときに、NULLが最初にソートされるのはなぜですか?

select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test

結果として

NULL
1
2
3
4

NULLは「不定」または「不明」の可能性があると考え続けます。その場合、値は他のすべての値よりも大きくなる可能性があるため、最後にソートしませんか?(または、これはどこかのソートオプションですか?)

私はSQL Server 2008R2を使用していますが、これはすべてのSQL Server、おそらくすべてのRDBMSに当てはまると思われます。


1
Oracleは最後にリストします。SQL Serverのように振る舞うべきだと信じて、一度私を混乱させました。
アンドレイリネア

2
「それが本当なら、値は他のすべての値よりも大きくなる可能性があるため、最後にソートしません」この値は、他のすべての値よりも小さい場合があります。私にとっては、nullのようなfalsey値が下端にあるべきであるということは直感的です。実際には、実際には、desc順序付けを使用して最大のものまたは最新のものを表示したいことがよくあります。その場合、nullのものが最後になることを嬉しく思います。
mahemoff

データベースは、ユーザーが指示したとおりに動作します。データにnullが含まれていることがわかっており、特定の方法でデータを並べ替えるビジネス上の理由がある場合は、クエリまたはデータを処理/表示するコード/ビューでそれを指定する必要があります。ソートをデフォルトのデータベース動作に任せないでください。
何も必要ない

回答:


19

BOL:NULLの値は、値が不明であることを示します。NULLの値は、空またはゼロの値とは異なります。等しい2つのnull値はありません。2つのNULL値の比較、またはNULLと他の値の比較は、各NULLの値が不明であるため不明を返します。

NULLは不明を意味します。他の解釈は無効です。

その場合、値は他のすべての値よりも大きくなる可能性があるため、最後にソートしませんか?

可能性はありません潜在的な価値はありません。Unknown is unknown is unknownです。

なぜ最後にではなく最初に表示されるのかについては、これは公開されているSQL標準では対応されておらず、残念ながらRDBMSベンダーの裁量に任されています。

ウィキペディア:SQL標準では、Nullのデフォルトのソート順は明示的に定義されていません。代わりに、適合システムでは、ORDER BYリストのNULLS FIRST句またはNULLS LAST句を使用して、すべてのデータ値の前または後にNullをソートできます。ただし、すべてのDBMSベンダーがこの機能を実装しているわけではありません。この機能を実装していないベンダーは、DBMSでNullソートに異なる処理を指定できます。


だから、それは判断の呼び出しです。それはとても理にかなっています。ありがとう!
リチャード

6

NULL「不確定」または「不明」または「不明」または「適用なし」を意味する可能性があります。しかし、ヌルを最初または最後に置く理由はありません。実際の値がわからない場合、tehyは小さくても大きくてもかまいません。

ソート中のNullの望ましい動作を決定するための標準は次のとおりです。

ORDER BY 
    test NULLS LAST                      --- or NULLS FIRST for the opposite

残念ながら、SQL-Serverはまだこの構文を採用していません。私が間違っていないなら、PostgreSQLとOracleにあります。

1つの解決策:

ORDER BY 
     CASE WHEN test IS NOT NULL 
            THEN 0 
          ELSE 1 
     END 
   , test

データ型に応じて調整が必要な別のソリューション-ただし、次のインデックスを使用できないため、うまく実行されません(test)

ORDER BY 
    COALESCE(test, 2147483647)               --- if it's a 4-byte signed integer

このように、ORDER BY COALESCE(test、2147483647)SQLサーバーはインデックスを使用できません。
アルダランシャーゴリ14年

3

私はそれがなぜそのように行われたの分かりませんが、定義によりNULLSは非NULLと比較することはできませんので、開始または終了のいずれかに行かなければなりません(マークの答えはこれをより詳細にカバーしています)。

必要な動作を取得するには-ヌルを最後に配置する並べ替えオプションがないので、計算列を使用して強制的に最後に配置する必要があります。ただし、SQL ServerではCASE WHEN ...、データにセット演算子(UNION ALL)が含まれている場合、計算列()で並べ替えることはできません。そう:

CREATE TABLE #sorttest(test int)
INSERT INTO #sorttest values(1)
INSERT INTO #sorttest values(5)
INSERT INTO #sorttest values(4)
INSERT INTO #sorttest values(NULL)
INSERT INTO #sorttest values(3)
INSERT INTO #sorttest values(2)
SELECT test
FROM #sorttest
ORDER BY CASE WHEN test IS NULL THEN 1 ELSE 0 END, test

DROP TABLE #sorttest

nullを最後にソートするために機能します。あなたが使用する必要がある場合UNION(またはEXCEPTまたはINTERSECTSデータセットを生成する)、その後、上記のように一時テーブルにデータをダンプします。


...またはUNIONされた出力を派生テーブルとして使用します。
アンドリーM

0

数字を扱っている場合は、次を使用することもできます

ORDER BY -test DESC

NULLは可能な最小値であるためDESC、最後に配置します。一方、非null値は符号が反転しているため、DESC実際には実際のASC値になります。これはCASE、クエリオプティマイザーがtest列のインデックスを使用するよりも高速であると考えられます。


3
いいえ、ソートにインデックスを使用することはできません。計算式にインデックスがない場合(- test)
ypercubeᵀᴹ

1
数値データのみに制限されていても、賢い(とにかくOPの例に適しています)。これが実際にCASEを使用するよりも速いかどうかはわかりませんが、インデックスを使用しないことは確かです(@ypercubeᵀᴹが言っている場合を除きます-しかし、CASE式はまったく同じ方法でインデックス付けできます)。
アンドリーM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.