在以下脚本中(请参阅此处的完整演示):
SELECT *
FROM Table1
ORDER BY
CASE WHEN Field1 IS NOT NULL
THEN 0
END
- 的类型是
0
什么? - 是如何
0
解释的?不是选择列表中列的序号,因为选择列表枚举是从 1 开始的,而不是 0。那么它是什么?
为了详细说明,将上面的代码段与以下代码段进行比较,它会发出错误:
SELECT *
FROM Table1
ORDER BY 0
ORDER BY 位置编号 0 超出了选择列表中的项目数范围。
并将其与以下代码段进行比较,该代码段会发出另一个错误:
SELECT *
FROM Table1
ORDER BY '0'
在 ORDER BY 列表的位置 1 中遇到常量表达式。
似乎将0
值嵌套在case
子句下使它起作用,但我不明白为什么以及如何?
- 这个问题在某种程度上是这个旧问题的后续问题,与我上面列出的替代方案相比,它没有解释为什么它可以工作: 如何使用 order by 0 工作 SQL?
ORDER BY 条款文档指出:
可以说,该文档可以更清楚地说明这一点。根据第二句,“列”可以指定为:
CASE
是“表达式”而不是列规范。该表达式未指定排序顺序列。表达式结果的值用于排序。表达式的结果
CASE WHEN Field1 IS NOT NULL THEN 0 END
是一个整数(由于整数常量为零),其值为 0 或NULL
。表达式类型信息可以通过以下方式收集sys.dm_exec_describe_first_result_set
:使用稍微修改的数据和有效的 CASE 表达式,您可以看到具有 NULL 值的行在具有非空值的行之前排序,因为 CASE 表达式为具有 NULL Field1 值的行返回 NULL,而对于具有 NULL 值的行返回零非空值。
我要补充一点,因为无论如何 NULL 都在非 NULL 值之前排序,所以可以简单地按 Field1 排序以提供所需的排序行为,也可能利用列上的索引。与 CASE 表达式不同,此方法还将根据 Field1 值而不是 CASE 表达式零值的未定义顺序(由于零值的关系)对非 NULL 值进行排序。
当您使用表达式(例如
CASE
)时,它不再按列名或列序号排序,而是现在按值排序。在这种情况下,您选择的值是 0(仅适用于非空Field1
行),但它可能是 1、100、'Red' 甚至FieldSomethingElse
.如果你
CASE
进一步构建你的表达,你会明白我的意思:Field1
以上根据 的值是否大于某个值对行进行半降序排序。它还有一个默认情况,即ELSE
子句,它将所有行放在Field1 IS NULL
结果的末尾。显然,没有名称或序数为 100、200、300 或 900 的列,但上述
CASE
表达式有效,因为 SQL Server 按子句中满足该子句的行的值对行进行排序。THEN
WHEN
当您使用 0 时,在您的示例子句中发生了同样的事情
CASE
,它只是对常量值 0 上的非空行进行排序。这显然在排序方面没有多大意义,除了所有非空行都将被排序一起(因为它们都将按相同的值 0 排序,因此它们在该排序中的顺序将是不确定的)并且所有空行也将一起排序。order 语句根据 case 条件生成一个包含 NULL 或 0 的“虚拟字段”。
基于该虚拟字段应用 ORDER BY。
order by 中的零值在 NULL 值之前。就是这样,这是一种在订单列表末尾设置 field1 的 NULL 的方法。
尝试以这种方式可视化它: