SQL昇順で並べ替えるときにnull値を最後にする方法


297

日時フィールドのあるSQLテーブルがあります。問題のフィールドはnullにすることができます。クエリがあり、日時フィールドで結果を昇順に並べ替えたいが、日時フィールドがリストの最初ではなく最後にnullである行が欲しい。

それを達成する簡単な方法はありますか?



回答:


394
select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate

2
ただし、パフォーマンスを改善するためにソート列にインデックスを配置すると(*)、この方法ではクエリプランが多少複雑になり、パフォーマンス上の利点の多くが失われることに注意してください。*-インデックスは、事前にソートされたデータを提供するため、クエリ実行ごとのソートを回避します。この問題を完全に回避するために、可能であればNULLレコードを除外することをお勧めします。
redcalx 2012年

2
また、利点と欠点を持つすべての可能な方法で、ここで与えられたニースの答えnickstips.wordpress.com/2010/09/30/...
sudhAnsu63

40
order by case when MyDate is null then 1 else 0 end言い方は本当に長いですORDER BY MyDate IS NULL
マーティン

5
@Martinこの質問にはmysqlのタグが付けられていないことに注意してください。私は一般的な解決策を提供しました-異なるデータベース間で同じことを行うには多くの異なる方法があります。
RedFilter 2015年

1
@KyleDelaney order by 0は列インデックスとして解釈されるため、列インデックスは1 から始まります。クエリを3番目の列で並べ替えるにはorder by 3(プロダクションクエリではひどい考えです)と言えますが、試してみると非常に便利です(そのままです*)。
RedFilter

159

(「少し」遅くなりますが、これはまったく言及されていません)

DBMSを指定していません。

標準のSQL(とOracle、PostgreSQLの、DB2、Firebirdの、Apache Derbyを、HSQLDBやH2などの最も近代的なDBMS)で次のように指定することができますNULLS LASTNULLS FIRST

NULLS LASTそれらを最後にソートするために使用します:

select *
from some_table
order by some_column DESC NULLS LAST

16
AFAIK NULLS FIRSTおよびNULLS LASTはSQL:2003で追加されましたが、さまざまなDMBS全体で使用できる標準実装はありません。データベースエンジンに応じて、ORDER BY expr some_column DESC NULLS LAST(Oracle)、ORDER BY ISNULL(some_column, 1), some_column ASC(MSSQL)、またはORDER BY ISNULL(some_column), some_column ASC(別のISNULL()実装のMySQL)を使用します。
SaschaM78 2013年

3
@ SaschaM78:NULLのデフォルトのソートはDBMSに依存します。一部を最後に並べ替え、一部を最初に並べ替えます。一部を約気にしないでくださいASC/ DESC一部が行うヌルで。したがって、これを確実にする唯一の方法は、DBMSがサポートしているNULL FIRST/LAST 場合に使用することです。それであなたが意図していることを文書化します。isnull()またはその他の関数の使用は、欠落しているサポートの回避策ですNULLS FIRST/LAST(Oracle、PostgreSQL、DB2、Firebird、Apache Derby、HSQLDBおよびH2でサポートされています)
a_horse_with_no_name 2013年

あなたは完全に正しいです、私は標準に(まだ)従わないか、OracleのようにexprNULLS FIRST / LASTを使用するときにキーワードを必要とするOracleのような彼らの専門があるかなりのDBMSがあるという事実を追加したかっただけです。そして、データベースのタイプごとに最初と最後に異なるnullが表示されることについて感謝します。
SaschaM78 2013年

2
これは有望に見えますが、悲しいことに、試してみNULLS LASTましたが、MySQLデータベースでは機能しませんでした。
AdmiralThrawn 2017年

1
@AdmiralAdama:Postgresにいつでもアップグレードできます
a_horse_with_no_name

35

私はこれにも偶然遭遇しましたが、MySQLとPostgreSQLでは次のようにうまくいくようです。

ORDER BY date IS NULL, date DESC

で見つかったように https://stackoverflow.com/a/7055259/496209


このルックスは有望な、しかし悲しいことに、私はそれを試してみましたIS NULLし、IS NOT NULL私のMySQLデータベースでは動作しませんでした。
AdmiralThrawn 2017年

14
order by coalesce(date-time-field,large date in future)

10
これは通常は機能しますが、この回答にはいくつかの問題があることに注意してください。将来の大きな日付は、実際のデータと衝突するか、実際のデータよりも少なくなり、ソートが不完全になる可能性があります。また、自己文書化しない「マジックナンバー」ソリューションです。
RedFilter 2009

問題の列を別の日付列と比較する必要がある場合、これは@RedFilterの回答の優れた代替手段になります。私はこれを組合の年功リストに使用します。従業員が認定日付(null可能)を持っている場合、その日付は先頭に記録されます。それ以外の場合はHireDateを使用します。ORDER BY ISNULL(QualifiedDate、 '1-1-2099')、HireDate、LastNameなどを使用すると、Qualified日付がHiredDate日付と競合せず、正しいセキュリティリストが生成されます。
アランフィッシャー

14

次のように、組み込み関数を使用してnullかどうかをチェックできます。私はそれとその動作をテストしました。

select MyDate from MyTable order by ISNULL(MyDate,1) DESC, MyDate ASC;


日付がmssqlで機能するようにするには、ISNULL関数に将来の日付を遠くに置くと便利です。つまり、ISNULL(MyDate、 '2100-01-01')
Emi-C

MySQLでは、渡したパラメータが多すぎると表示されています。を実行してこれを解析しISNULL(MyDate) DESC, MyDate ASCましたが、正しい順序で並べ替えられませんでした。
AdmiralThrawn 2017年

12

エンジンが許可する場合、ORDER BY x IS NULL, xまたはORDER BY x NULLS LAST使用している場合。しかし、それが役に立たない場合は、次の方法が役立つ可能性があります。

数値タイプで並べ替える場合は、次のようにできます(別の回答からスキーマを借用します)。

SELECT *          
FROM Employees
ORDER BY ISNULL(DepartmentId*0,1), DepartmentId;

最後にnullを含む部門IDでソートされた結果

null以外の数値はすべて0になり、nullは1になり、nullは最後にソートされます。

文字列に対してこれを行うこともできます。

SELECT *
FROM Employees
ORDER BY ISNULL(LEFT(LastName,0),'a'), LastName

最後にnullを含むLastNameでソートされた結果

なぜなら'a'> ''

これは、null許容のintに強制変換し、上記のintのメソッドを使用することにより、日付でも機能します。

SELECT *
FROM Employees
ORDER BY ISNULL(CONVERT(INT, HireDate)*0, 1), HireDate

(スキーマにHireDateがあると仮定します。)

これらのメソッドは、データタイプ(および最大値)が変更された場合に、すべてのタイプの「最大」値を考え出すか管理するか、クエリを修正する必要があるという問題を回避します(他のISNULLソリューションが抱える問題の両方)。さらに、CASEよりもはるかに短いです。


よく働く !ありがとう
バニ

8

注文列が数値(ランクなど)の場合、-1を掛けてから降順で並べ替えることができます。それはあなたが期待している注文を維持しますが、最後にNULLを置きます。

select *
from table
order by -rank desc

これについてコメントしようとしていたところです。stackoverflow.com/a/8174026/1193304からそれを学び、それは素晴らしい
Chris


3

null可能な日付時刻フィールドの並べ替えのバグの問題に対する優れたソリューションを提供してくれたRedFilterに感謝します。

プロジェクトにSQL Serverデータベースを使用しています。

datetimeのnull値を「1」に変更すると、datetimeデータ型列の並べ替えの問題が解決されます。ただし、datetimeデータ型以外の列がある場合は、処理に失敗します。

varchar列の並べ替えを処理するために、「ZZZZZZZ」を使用してみました。列に「Z」で始まる値がないことがわかっているためです。期待通りに動きました。

同じ行で、intおよびその他のデータ型に最大値+1を使用して、期待どおりに並べ替えを行いました。これにより、必要な結果も得られました。

ただし、データベースエンジン自体で次のようなことを実行できる簡単なものを取得することが常に理想的です。

Order by Col1 Asc Nulls Last, Col2 Asc Nulls First 

a_horse_with_no_nameが提供する回答で述べたように。



3

MariaDBを使用している場合、NULL値のドキュメントで次のように述べられています

ご注文

NULL値を含む可能性のあるフィールドで並べ替えると、NULLは最も低い値を持つと見なされます。したがって、DESC順に並べ替えると、NULLが最後に表示されます。NULLを最も高い値と見なすようにするには、メインフィールドがNULLのときに、より高い値を持つ別の列を追加します。例:

SELECT col1 FROM tab ORDER BY ISNULL(col1), col1;

降順、最初にNULLを使用:

SELECT col1 FROM tab ORDER BY IF(col1 IS NULL, 0, 1), col1 DESC;

すべてのNULL値は、DISTINCT句とGROUP BY句の目的でも同等と見なされます。

上記はNULL値による順序付けの2つの方法を示しています。これらをASCおよびDESCキーワードと組み合わせることもできます。たとえば、最初にNULL値を取得する別の方法は次のとおりです。

SELECT col1 FROM tab ORDER BY ISNULL(col1) DESC, col1;
--                                         ^^^^

2

「ケース」を使用した解決策は一般的ですが、インデックスを使用しないでください。

order by case when MyDate is null then 1 else 0 end, MyDate

私の場合、パフォーマンスが必要でした。

 SELECT smoneCol1,someCol2  
 FROM someSch.someTab
 WHERE someCol2 = 2101 and ( someCol1 IS NULL ) 
  UNION   
 SELECT smoneCol1,someCol2
 FROM someSch.someTab
 WHERE someCol2 = 2101 and (  someCol1 IS NOT NULL)  

1
パフォーマンスに関心がある場合は、を使用する必要がありますUNION ALL
RedFilter、2015年


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.