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,您可以:
-
添加另一个字段,仅用于sorting,如Next_Contact_Date_Sort。
-
使用大(或小)值创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 FIRST
或NULLS LAST
,最简单的方法是使用value IS NULL
expression式:
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,并且比CASE
expression式更容易阅读。
编辑:唉,虽然这工作在其他SQL实现像PostgreSQL和MySQL,它不能在MS SQL Server中工作。 我没有一个SQL Server来testing,依靠微软的文档和其他SQL实现testing。 据微软称, value IS NULL
是一个expression式应该可以像任何其他expression式一样使用。 ORDER BY
应该像expression式那样使用expression式。 但它并不实际工作。
因此,SQL Server的最佳解决scheme似乎是CASE
expression式。
如果需要,使用desc并乘以-1。 用空值递增intsorting的示例last:
select * from (select null v union all select 1 v union all select 2 v) t order by -tv desc