SQL Server ORDERBYの日付とnullの最後


82

日付で注文しようとしています。最新の日付を最初に入力してください。これは簡単ですが、nullのレコードが多数あり、日付のあるレコードの前にあります。

私はいくつかのことを試みましたが成功しませんでした:

ORDER BY ISNULL(Next_Contact_Date, 0)

ORDER BY ISNULL(Next_Contact_Date, 999999999)

ORDER BY coalesce(Next_Contact_Date, 99/99/9999)

日付で注文してヌルを最後に入れるにはどうすればよいですか?データ型はsmalldatetimeです。


ソート順は昇順である必要がありますが、最後にnullがありますか?そして、あなたはあなたのテーブルに将来の日付を持っていますか?
AllenG 2011年

@AllenG、ええ、過去から未来へ、過去を最初に、というように。そうそう、昇順。はい、将来の日付はそれらのほとんどがどうなるかです。
upHelix 2011年

回答:


112

smalldatetime 2079年6月6日までの範囲があるため、使用できます

ORDER BY ISNULL(Next_Contact_Date, '2079-06-05T23:59:00')

正当な記録にその日付がない場合。

これが前提ではない場合、より堅牢なオプションに頼るのは2つの列で並べ替えることです。

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

上記の両方の提案では、インデックスを使用して並べ替えを回避し、同様の外観の計画を立てることはできません。

ここに画像の説明を入力してください

そのようなインデックスが存在する場合のもう1つの可能性は

SELECT 1 AS Grp, Next_Contact_Date 
FROM T 
WHERE Next_Contact_Date IS NOT NULL
UNION ALL
SELECT 2 AS Grp, Next_Contact_Date 
FROM T 
WHERE Next_Contact_Date IS NULL
ORDER BY Grp, Next_Contact_Date

予定


このトリックはVARCHARフィールドにも適用でき(例ORDER BY ISNULL(my_varchar, 'ZZZZZZ'))、特にを使用するときに特定の方法で注文を取得する場合に非常に役立ちGROUP BY . . . GROUPING SETSます。これを投稿していただきありがとうございます。
sparc_spread

order by descを使用してnullを下部に配置できないのはなぜですか?また、なぜnullを1にマップするのですか?
MasterJoe

35

Itzikベン・ガン、の著者によると、MS SQL Server 2012のためのT-SQLの基本、「デフォルトでは、SQL Serverは、ソートのNULL以外の前にマークをNULLの値。取得するにはNULLを最後にソートするマークを、あなたが使用することができますCASEのリターンという表現を1「 Next_Contact_DateカラムはNULL、」0そうでない場合はNULL非。 NULLのマークが式から0を取り戻すため、それらはソート前のNULL(1得る)マークこのCASEの発現は最初として使用されます並べ替え列。」Next_Contact_Datecolumn "2番目の並べ替え列として指定する必要があります。このように、NULL以外のマークはそれらの間で正しく並べ替えられます。" MS SQL Server 2012(およびSQL Server 2014)の例のソリューションクエリは次のとおりです。

ORDER BY 
   CASE 
        WHEN Next_Contact_Date IS NULL THEN 1
        ELSE 0
   END, Next_Contact_Date;

IIF構文を使用した同等のコード:

ORDER BY 
   IIF(Next_Contact_Date IS NULL, 1, 0),
   Next_Contact_Date;

また、答えに追加するために、IIFの1と0を切り替えると、ヌルが一番上に移動します。これは、タプルをテーブルの一番上に配置して単一のタプルが必要な場合にも機能します。
FrancoPettigrosso19年

3

SQLがNULLS FIRSTまたはをサポートしていない場合、NULLS LASTこれを行う最も簡単な方法は、次のvalue IS NULL式を使用することです。

ORDER BY Next_Contact_Date IS NULL, Next_Contact_Date

最後にnullを置く(NULLS LAST)または

ORDER BY Next_Contact_Date IS NOT NULL, Next_Contact_Date

nullを前面に配置します。これは、列のタイプを知る必要がなく、より読みやすいです。CASEです。

編集:残念ながら、これはPostgreSQLやMySQLなどの他のSQL実装では機能しますが、MS SQLServerでは機能しません。テストするSQLServerがなく、Microsoftのドキュメントと他のSQL実装でのテストに依存していました。Microsoftによると、value IS NULL 他の式と同じように使用できるはずの式です。そしてORDER BY 、表現を取ることになっています、式を取る他のステートメントと同じように。しかし、実際には機能しません。

したがって、SQL Serverの最適なソリューションは、CASE式であるように見えます。


7
これは有効なSQLServer構文ではありません
Martin Smith

3
申し訳ありません。それはすべきですMicrosoftのドキュメントに従って有効であり、他のSQLでも機能するですが、MSでは実際には許可されていません。
Vroo 2013

パフォーマンスに関しては、これはひどいように聞こえます2つの並べ替え基準を実行しています
ColacX 2016

あなたがリンクしたMicrosoftのドキュメントで、私はその値がNULLであることを読みましたではなく、述語。それは同じではありません。
BertuPG 2018

1
Microsoftによると、述語は式です。これは、文字通りdocs.microsoft.com/en-us/sql/t-sql/queries/predicatesの
Vroo

3
order by -cast([Next_Contact_Date] as bigint) desc

Next_Contact_Datenullの場合はエラーをスローしますExplicit conversion from data type date to bigint is not allowed.
Nerdroid 2017年

2

少し遅れますが、誰かがそれが役に立つと思うかもしれません。

私にとって、ISNULLは、テーブルスキャンのために問題外でした。UNION ALLでは、複雑なクエリを繰り返す必要があり、TOP Xのみを選択したため、あまり効率的ではありませんでした。

テーブルのデザインを変更できる場合は、次のことができます。

  1. Next_Contact_Date_Sortなど、並べ替えのためだけに別のフィールドを追加します。

  2. 必要なものに応じて、そのフィールドに大きな(または小さな)値を入力するトリガーを作成します。

    CREATE TRIGGER FILL_SORTABLE_DATE ON YOUR_TABLE AFTER INSERT,UPDATE AS 
    BEGIN
        SET NOCOUNT ON;
        IF (update(Next_Contact_Date)) BEGIN
        UPDATE YOUR_TABLE SET Next_Contact_Date_Sort=IIF(YOUR_TABLE.Next_Contact_Date IS NULL, 99/99/9999, YOUR_TABLE.Next_Contact_Date_Sort) FROM inserted i WHERE YOUR_TABLE.key1=i.key1 AND YOUR_TABLE.key2=i.key2
        END
    END
    

2

descを使用し、必要に応じて-1を掛けます。最後にnullを使用したintの昇順の例:

select * 
from
(select null v union all select 1 v union all select 2 v) t
order by -t.v desc

...これは、日付のような変数のために働くとは思わない
シャーロットトウ

1

私はこれが古いことを知っていますが、これは私のために働いたものです

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