【问题标题】:TSQL ORDER BY with nulls first or last (at bottom or top)TSQL ORDER BY 第一个或最后一个空值(在底部或顶部)
【发布时间】:2017-03-23 20:48:38
【问题描述】:

我有一个日期列,其中包含一些NULL。我想按日期列 ASC 排序,但我需要 NULL 位于底部。如何在 TSQL 上做到这一点?

【问题讨论】:

标签: sql-server tsql sql-order-by isnull


【解决方案1】:

在标准 SQL 中,您可以指定放置空值的位置:

order by col asc nulls first
order by col asc nulls last
order by col desc nulls first
order by col desc nulls last

但是 T-SQL 不符合这里的标准。 NULL 的顺序取决于你在 T-SQL 中是升序还是降序:

order by col asc -- implies nulls first
order by col desc -- implies nulls last

使用整数,您可以简单地按负数排序:

order by -col asc -- sorts by +col desc, implies nulls first
order by -col desc -- sorts by +col asc, implies nulls last

但这对于日期(或字符串)是不可能的,因此您必须首先按 is null / is not null 排序,然后才能按您的列:

order by case when col is null then 1 else 2 end, col asc|desc -- i.e. nulls first
order by case when col is null then 2 else 1 end, col asc|desc -- i.e. nulls last

【讨论】:

  • +1 用于指出标准与 TSQL 的区别。 order by col asc 首先给出空值,order by col desc 最后给出空值,因为 SQL Server 将 Null 值视为可能的最低值,请参阅 SELECT - ORDER BY Clause
  • 喜欢按负数排序整数!
  • 应该提到case when 解决方案对性能有显着的负面影响,不应在大型数据集上执行。 (source)
  • 当对字符串做同样的事情时,任何人都会想到比:CASE WHEN col IS NULL THEN 'ZZZZZZZ' ELSE col END
  • 也可以用更短的IIF(col IS NULL, 0, 1)代替case when col is null then 1 else 2 end
【解决方案2】:
Select *
 From  YourTable
 Order By case when DateCol is null then 0 else 1 end
         ,DateCol

甚至Order By IsNull(DateCol,'2525-12-31')

【讨论】:

  • 确保您记录了 500 年后需要进行的额外代码审查。技术债务真的可以加起来!
【解决方案3】:

order by case when col_name is null then 1 else 2 end, col_name asc 在 Oracle 上成功了。然而,在 MS SQL Server 上也是如此,会将 NULL 记录向下推,将非 null 记录在结果集的顶部。

【讨论】:

  • 当 col_name 为 null 然后 1 else 2 end DESC,col_name asc 在 MS SQL 和 Oracle 中时,应该按大小写排序
  • 或者当 col_name 为 null 然后 2 else 1 end, col_name asc 时按大小写排序
  • 简单。正是我想要的。
【解决方案4】:

这对我来说刚刚成功。幸运的是,我正在处理文本。对于任何数字,我可能会选择所有 9。 COALESCE(c.ScrubbedPath,'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'),

【讨论】:

  • 最初的问题是关于排序date 值,而不是文本,也不是数值。此外,通常首选通用的、始终适用的解决方案,而不是像 zzzzz... 这样的硬编码值。
  • @Sander - 根据问题标题,将问题更笼统地对待并非不合理 - 如何将空值排序在前或后,关于按日期排序的详细信息只是一个示例。跨度>
【解决方案5】:

有时,您可能需要使用子查询才能做到这一点:

 select site_id, site_desc
    from (
    select null as site_id, 'null' as site_desc
    union
    select s.site_id,
        s.site_code+'--'+s.site_description as site_desc
    from site_master s with(nolock)
    )x
    order by (case when site_id is null then 0 else 1 end), site_desc

【讨论】:

    猜你喜欢
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 2021-11-19
    • 2021-10-05
    • 1970-01-01
    相关资源
    最近更新 更多