【问题标题】:Order by multiple columns, ignoring Null按多列排序,忽略 Null
【发布时间】:2023-04-08 13:33:01
【问题描述】:

我有一个视图,它显示某个物品到达多个位置的时间。我想根据到达时间订购这个视图:

ITEM | At Loc1 | At Loc2 | At Loc3 | At Loc4 | Desired Order
--------------------------------------------------------
aaa  | 00:00   | 02:01   | NULL    | 05:30   | 0
bbb  | NULL    | 02:30   | 06:21   | NULL    | 1
ccc  | 00:05   | 02:33   | NULL    | 07:10   | 2 
ddd  | 00:07   | NULL    | 06:25   | 09:00   | 3
eee  | NULL    | NULL    | 06:30   | 09:10   | 4
fff  | 00:30   | 02:55   | 06:32   | NULL    | 5

有时,由于测量错误或不规则,无法记录到达时间。在那种情况下,时间是NULL

现在我想Select * from View ORDER BY AtLoc1 ASC, AtLoc2 ASC, AtLoc3 ASC, AtLoc4 ASC

但列中的 Null 值不应导致项目移到前面或后面。它应该根据下一列保持在正确的相对位置。

比如item bbb在位置1没有记录,但是在aaa之后ccc之前到达了位置2,所以应该在aaa和ccc之间排序,而不是在列表的开头或结尾

在大多数情况下,项目不会在位置之间更改它们的顺序,但这并非不可能。

我不认为我可以为所有特殊情况定义唯一且明确定义的排序顺序,当有太多 NULL 聚集在一起时,顺序可能未定义。但我只想介绍空值相对稀疏的最常见情况。

如何以这种方式在 SQL 中对视图进行排序?

【问题讨论】:

  • 嗯,PIVOT 然后 ORDER BY 然后 UNPIVOT?这是一个棘手的问题。

标签: sql sql-server null sql-order-by sql-server-2016


【解决方案1】:

需要更多测试,但试试这个:

SQL DEMO

WITH cte as (
    SELECT *, 
           CASE WHEN [At Loc1] IS NOT NULL 
                THEN row_number() over (order by  [At Loc1] ) 
           END as r1,
           CASE WHEN [At Loc2] IS NOT NULL 
                THEN row_number() over (order by  [At Loc2] ) 
           END as r2,
           CASE WHEN [At Loc3] IS NOT NULL 
                THEN row_number() over (order by  [At Loc3] ) 
           END as r3,
           CASE WHEN [At Loc4] IS NOT NULL 
                THEN row_number() over (order by  [At Loc4] ) 
           END as r4
    FROM Table1
)
SELECT *, COALESCE(r1,r2,r3,r4)
FROM cte
ORDER BY COALESCE(r1,r2,r3,r4),
         COALESCE(r2,r3,r4),
         COALESCE(r3,r4),
         r4
;

输出

【讨论】:

    【解决方案2】:

    不,你不能得到一个稳定的排序,因为你可以有这样的东西:

    aaa     1      7
    bbb  NULL      6
    ccc     2      5
    

    基本上,这三件事都是真的:

    • ccc > aaa
    • bbb > ccc
    • aaa > bbb

    这些不可能同时为真(至少对于我们通常使用的数字或时间来说不是)。

    Juan Carlos 提供了一个非常好的临时解决方案,但它并非在所有情况下都有效。

    【讨论】:

    • 谢谢戈登。我知道有很多案例,但我无法全部测试。为了清楚起见并供参考,这是我使用 Gordon 数据 rextester.com/ULYBQ46358 查询的结果
    猜你喜欢
    • 2011-07-11
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2013-04-11
    • 2016-01-10
    相关资源
    最近更新 更多