我想按日期订购。我希望最近的日期排在第一位。这很容易,但是有许多记录为空,并且在任何有日期的记录之前。
我尝试了一些没有成功的事情:
ORDER BY ISNULL(Next_Contact_Date, 0)
ORDER BY ISNULL(Next_Contact_Date, 999999999)
ORDER BY coalesce(Next_Contact_Date, 99/99/9999)
如何按日期排序并让空值排在最后?数据类型为smalldatetime
。
我想按日期订购。我希望最近的日期排在第一位。这很容易,但是有许多记录为空,并且在任何有日期的记录之前。
我尝试了一些没有成功的事情:
ORDER BY ISNULL(Next_Contact_Date, 0)
ORDER BY ISNULL(Next_Contact_Date, 999999999)
ORDER BY coalesce(Next_Contact_Date, 99/99/9999)
如何按日期排序并让空值排在最后?数据类型为smalldatetime
。
Answers:
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
上述两个建议均不能使用索引来避免排序,并给出相似的计划。
如果存在这样的索引,另一种可能性是
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
。感谢您发布此信息。
据伊茨克奔甘,作者T-SQL基础对MS SQL Server 2012中,“默认情况下,SQL Server的排序NULL之前非标记NULL值。要获得NULL痕最后排序,你可以使用一个CASE表达式返回1当“ Next_Contact_Date列是NULL,”和0时,它不是NULL非。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;
如果您的SQL不支持NULLS FIRST
或NULLS 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
表达式更容易阅读。
编辑:las,虽然这可以在其他SQL实现(例如PostgreSQL和MySQL)中使用,但在MS SQL Server中不起作用。我没有SQL Server可以测试,也没有依赖Microsoft的文档和其他SQL实现的测试。根据Microsoft的说法,value IS NULL
该表达式应该与其他任何表达式一样可用。并且ORDER BY
应该像接受其他任何使用表达式的语句一样使用表达式。但这实际上不起作用。
因此,SQL Server的最佳解决方案似乎是CASE
表达式。
有点晚了,但也许有人觉得它有用。
对我来说,由于表扫描,ISNULL毫无疑问。UNION ALL将需要我重复一个复杂的查询,并且由于我只选择了TOP X,所以效率不是很高。
如果您能够更改表格设计,则可以:
添加另一个用于排序的字段,例如Next_Contact_Date_Sort。
创建一个触发器,该触发器根据需要使用较大(或较小)值填充该字段:
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