SQL Server ORDER BYdate和空值最后

我正在尝试按datesorting。 我希望最近的date进来。 这很简单,但是有很多logging是空的,并且在任何有date的logging之前。

我尝试了一些没有成功的事情:

ORDER BY ISNULL(Next_Contact_Date, 0) ORDER BY ISNULL(Next_Contact_Date, 999999999) ORDER BY coalesce(Next_Contact_Date, 99/99/9999) 

我怎样才能按datesorting,最后还有空值? 数据types是smalldatetime

smalldatetime范围可以达到2079年6月6日,所以你可以使用

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

如果没有合法的logging会有这个date。

如果这不是一个假设,你喜欢依靠更强大的选项是sorting在两列。

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

上述两个build议都不能使用索引来避免sorting,并给出类似的计划。

在这里输入图像说明

如果存在这样的指数,另一种可能性是

 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 

计划

根据MS SQL Server 2012 T-SQL基础的作者Itzik Ben-Gan的说法,“默认情况下,SQL Server在非NULL值之前对NULL标记进行sorting,要获得最后sorting的NULL标记,可以使用CASEexpression式返回如果“ Next_Contact_Date列为 NULL则为 1;如果为NULL则为 0;非NULL标记从该expression式返回0;因此,它们在NULL标记之前sorting(得到1),这个CASEexpression式被用作第一个分类栏“。 Next_Contact_Date列“应该被指定为第二个sorting列。这样,非NULL标记在它们之间正确sorting。 以下是MS SQL Server 2012(和SQL Server 2014)示例的解决scheme查询:

 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; 

有点晚了,但也许有人觉得它有用。

对我来说,由于表扫描,ISNULL是没有问题的。 UNION ALL需要我重复一个复杂的查询,而且由于我只selectTOP X,所以效率不会很高。

如果您可以更改表格devise,您可以:

  1. 添加另一个字段,仅用于sorting,如Next_Contact_Date_Sort。

  2. 使用大(或小)值创build一个触发器来填充该字段,具体取决于您需要的内容:

     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 
 order by -cast([Next_Contact_Date] as bigint) desc 

标准的ANSI方法是:

 ORDER BY Next_Contact_Date ASC NULLS LAST 

请注意,相反NULLS FIRST也存在。

如果您的SQL不支持NULLS FIRSTNULLS LAST ,最简单的方法是使用value IS NULLexpression式:

 ORDER BY Next_Contact_Date IS NULL, Next_Contact_Date 

将Null放在最后( NULLS LAST )或

 ORDER BY Next_Contact_Date IS NOT NULL, Next_Contact_Date 

把零点放在前面 这不需要知道列的types,并且比CASEexpression式更容易阅读。

编辑:唉,虽然这工作在其他SQL实现像PostgreSQL和MySQL,它不能在MS SQL Server中工作。 我没有一个SQL Server来testing,依靠微软的文档和其他SQL实现testing。 据微软称, value IS NULL 是一个expression式应该可以像任何其他expression式一样使用。 ORDER BY 应该像expression式那样使用expression式。 但它并不实际工作。

因此,SQL Server的最佳解决scheme似乎是CASEexpression式。

如果需要,使用desc并乘以-1。 用空值递增intsorting的示例last:

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