SQL Server ORDER BY日期和空值最后

时间:2011-05-04 16:43:32

标签: sql-server sql-server-2005 tsql

我想按日期订购。我希望最新的日期出现在第一位。这很容易,但有许多记录为空,而且这些记录在任何有日期的记录之前。

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

ORDER BY ISNULL(Next_Contact_Date, 0)

ORDER BY ISNULL(Next_Contact_Date, 999999999)

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

如何按日期订购并让空值最后?数据类型为smalldatetime

7 个答案:

答案 0 :(得分:94)

smalldatetime的范围可达2079年6月6日,因此您可以使用

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

如果没有合法记录的那个日期。

如果这不是假设,那么您希望依赖更强大的选项来排序两列。

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

上述两个建议都无法使用索引来避免排序,而是提供类似的计划。

enter image description here

如果存在这样的索引,则另一种可能性是

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

Plan

答案 1 :(得分:21)

根据 T-SQL基础知识MS SQL Server 2012 的作者Itzik Ben-Gan的说法,“默认情况下,SQL Server排序 NULL NULL 值之前的标记。要使 NULL 标记最后排序,您可以使用 CASE 表达式,当 Next_Contact_Date 列为 NULL 时返回1 strong>,“当 NULL 时为0,非 NULL 标记从表达式返回0 ;因此,它们在 NULL 标记(获得1)之前排序。此 CASE 表达式用作第一个排序栏。“应将 Next_Contact_Date 列指定为第二个排序列。这样,非 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;

答案 2 :(得分: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
    

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

ORDER BY Next_Contact_Date IS NULL, Next_Contact_Date

将空值放在末尾(NULLS LAST)或

ORDER BY Next_Contact_Date IS NOT NULL, Next_Contact_Date

将空值放在前面。这不需要知道列的类型,并且比CASE表达式更容易阅读。

编辑:唉,虽然这适用于其他SQL实现,如PostgreSQL和MySQL,但它在MS SQL Server中不起作用。我没有SQL Server来测试和依赖Microsoft的文档和测试与其他SQL实现。据微软称,value IS NULL is an expression应该可以像任何其他表达式一样使用。 ORDER BY is supposed to take expressions就像任何其他表达式的语句一样。但它实际上并不起作用。

因此,SQL Server的最佳解决方案似乎是CASE表达式。

答案 5 :(得分:1)

使用desc并在必要时乘以-1。最后使用nulls升序int排序的示例:

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

答案 6 :(得分:0)

我知道这很老了,但这对我有用

Order by Isnull(Date,'12/31/9999')