SQL排序升序时如何使空值最后

Dav*_*jak 280 sql sorting sql-order-by

我有一个带有日期时间字段的SQL表.有问题的字段可以为null.我有一个查询,我希望结果按日期时间字段按升序排序,但是我想要在列表末尾的日期时间字段为空的行,而不是在开头.

有没有一种简单的方法来实现这一目标?

Red*_*ter 373

select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate
Run Code Online (Sandbox Code Playgroud)

  • `当MyDate为空时按顺序排列,然后是1,0结束`是一个非常长的说法`ORDER BY MyDate IS NULL (33认同)
  • @Martin注意这个问题没有标记为mysql.我提供了一个通用的解决方案 - 在不同的dbs中有很多不同的方法可以做同样的事情. (4认同)
  • @KyleDelaney 如前所述,“order by 0”中的 0 被视为列索引,而 case 语句中的 0 被视为“虚拟”列中的值(如果有意义的话)。您还可以尝试“order by (select 0)”,这将起作用,因为数据库引擎将其解释为虚拟列的列值,而添加该虚拟列只是为了对输出进行排序。 (3认同)
  • 但是请注意,如果您在排序列上放置索引以提高性能(*),则此方法将使查询计划复杂化,并失去很多性能优势。*-索引提供了预先排序的数据,因此避免了每次查询执行的排序。建议尽可能过滤掉NULL记录,以完全避免此问题。 (2认同)
  • 这里也给出了很好的答案,其中包含所有可能的优点和缺点 http://nickstips.wordpress.com/2010/09/30/sql-order-by-with-null-values-last/ (2认同)
  • @KyleDelaney 因为`order by 0` 被解释为列索引,并且列索引是从 1 开始的。要按第 3 列对查询进行排序,您可以说“按 3 排序”(这对于生产查询来说是一个糟糕的主意),但在试验时非常方便(就像“*”一样)。 (2认同)

a_h*_*ame 152

("有点"迟到,但这根本没有提到)

您没有指定DBMS.

在标准SQL(以及大多数现代DBMS,如Oracle,PostgreSQL,DB2,Firebird,Apache Derby,HSQLDB和H2)中,您可以指定NULLS LASTNULLS FIRST:

用于NULLS LAST将它们排序到最后:

select *
from some_table
order by some_column DESC NULLS LAST
Run Code Online (Sandbox Code Playgroud)

  • 在SQL:2003中添加了AFAIK`NULLS FIRST`和`NULLS LAST`,但在不同的DMBS中没有可用的标准实现.根据数据库引擎,使用`ORDER BY expr some_column DESC NULLS LAST`(Oracle),`ORDER BY ISNULL(some_column,1),some_column ASC`(MSSQL)或`ORDER BY ISNULL(some_column),some_column ASC`(MySQL有一个不同的ISNULL()实现). (15认同)
  • @ SaschaM78:NULL的默认排序取决于DBMS.有些人在最后排序,有些在开头.有些人不关心`ASC` /`DESC`和nulls.因此,确保这一点的唯一方法是使用"NULL FIRST/LAST"**,如果**DBMS支持它.在它*文件*你想要什么.使用`isnull()`或其他函数是缺少对'NULLS FIRST/LAST`的支持的解决方法(由Oracle,PostgreSQL,DB2,Firebird,Apache Derby,HSQLDB和H2支持) (3认同)
  • 这看起来很有希望,但遗憾的是,我尝试了它并且 `NULLS LAST` 在我的 MySQL 数据库中不起作用。 (3认同)
  • @AdmiralAdama:你可以随时升级到 Postgres (2认同)

Luk*_*ous 32

我也偶然发现了这一点,以下似乎对我来说,在MySQL和PostgreSQL上的诀窍:

ORDER BY date IS NULL, date DESC
Run Code Online (Sandbox Code Playgroud)

见于/sf/answers/493868161/


Gra*_*tzy 14

order by coalesce(date-time-field,large date in future)
Run Code Online (Sandbox Code Playgroud)

  • 虽然这通常会起作用,但应该注意这个答案有一些问题:将来的大日期可能会与实际数据冲突或者比实际数据少,导致排序不完美.此外,它是一个"神奇的数字"解决方案,不是自我记录. (10认同)

小智 13

您可以使用内置函数检查null或not null,如下所示.我测试它,它的工作正常.

select MyDate from MyTable order by ISNULL(MyDate,1) DESC, MyDate ASC;


inf*_*lch 12

如果您的引擎允许ORDER BY x IS NULL, xORDER BY x NULLS LAST使用它.但如果不是这些可能会有所帮助:

如果您按数字类型排序,则可以执行以下操作:(从另一个答案中借用模式.)

SELECT *          
FROM Employees
ORDER BY ISNULL(DepartmentId*0,1), DepartmentId;
Run Code Online (Sandbox Code Playgroud)

结果显示由DepartmentId排序,最后为空

任何非空数字都将变为0,空值变为1,最后对空值进行排序.

您也可以为字符串执行此操作:

SELECT *
FROM Employees
ORDER BY ISNULL(LEFT(LastName,0),'a'), LastName
Run Code Online (Sandbox Code Playgroud)

结果显示由LastName排序,最后为null

因为'a'> ''.

这甚至可以通过强制转换为可空int并使用上面的int方法来处理日期:

SELECT *
FROM Employees
ORDER BY ISNULL(CONVERT(INT, HireDate)*0, 1), HireDate
Run Code Online (Sandbox Code Playgroud)

(让我们假装架构有HireDate.)

这些方法避免了必须提出或管理每种类型的"最大"值的问题,或者如果数据类型(和最大值)发生变化(两个ISNULL解决方案都受到影响),则必须修复查询.而且它们比CASE短得多.


Lui*_*grs 7

当您的订单栏是数字(如排名)时,您可以将其乘以-1然后按顺序递减.它将保持您预期的顺序,但最后将NULL设置为NULL.

select *
from table
order by -rank desc
Run Code Online (Sandbox Code Playgroud)


Joa*_*tos 6

在 Oracle 中,您可以使用NULLS FIRSTor NULLS LAST: 指定应在非 NULL 值之前/之后返回 NULL 值:

ORDER BY { column-Name | [ ASC | DESC ] | [ NULLS FIRST | NULLS LAST ] }
Run Code Online (Sandbox Code Playgroud)

例如:

ORDER BY date DESC NULLS LAST
Run Code Online (Sandbox Code Playgroud)

参考:http://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj13658.html


小智 5

SELECT *          
FROM Employees
ORDER BY ISNULL(DepartmentId, 99999);
Run Code Online (Sandbox Code Playgroud)

请参阅此博客文章


3li*_*t0r 5

如果您使用的是 MariaDB,他们会在NULL 值文档 中提到以下内容

订购

当您按可能包含 NULL 值的字段排序时,任何 NULL 都被视为具有最低值。因此,按 DESC 顺序排序将看到最后出现的 NULL。为了强制将 NULL 视为最高值,可以添加另一列,当主字段为 NULL 时,该列具有更高的值。例子:

SELECT col1 FROM tab ORDER BY ISNULL(col1), col1;
Run Code Online (Sandbox Code Playgroud)

降序,首先是 NULL:

SELECT col1 FROM tab ORDER BY IF(col1 IS NULL, 0, 1), col1 DESC;
Run Code Online (Sandbox Code Playgroud)

就 DISTINCT 和 GROUP BY 子句而言,所有 NULL 值也被视为等效。

上面显示了两种按 NULL 值排序的方法,您也可以将它们与 ASC 和 DESC 关键字结合使用。例如,首先获取 NULL 值的另一种方法是:

SELECT col1 FROM tab ORDER BY ISNULL(col1) DESC, col1;
--                                         ^^^^
Run Code Online (Sandbox Code Playgroud)