按零排序如何工作

Hey*_*ude 3 sql-server order-by

在以下脚本中(请参阅此处的完整演示):

SELECT *
FROM Table1
ORDER BY 
   CASE WHEN Field1 IS NOT NULL 
     THEN 0 
   END
Run Code Online (Sandbox Code Playgroud)
  • 的类型是什么0
  • 0是如何解读的呢?它不是选择列表中列的序号,因为选择列表枚举从 1 开始,而不是 0。那么它是什么?

为了详细说明一下,将上面的代码片段与下面的代码片段进行比较,这会发出一个错误:

SELECT *
FROM Table1
ORDER BY 0  
Run Code Online (Sandbox Code Playgroud)

ORDER BY 位置号 0 超出了选择列表中的项目数范围。

还将其与以下代码片段进行比较,该代码片段会发出另一个错误:

SELECT *
FROM Table1
ORDER BY '0'
Run Code Online (Sandbox Code Playgroud)

在 ORDER BY 列表的位置 1 中遇到常量表达式。

似乎将0值嵌套在case子句下可以使其工作,但我不明白为什么以及如何?

  • 这个问题在某种程度上是这个旧问题的后续问题,它并没有解释为什么它与我上面列出的替代方案相比有效: How does work SQL with order by 0?

Dan*_*man 8

ORDER BY 子句文档指出:

按表达式排序

指定对查询结果集进行排序的列或表达式。排序列可以指定为名称或列别名,或者表示该列在选择列表中的位置的非负整数。

可以说,医生可以更清楚地说明这一点。根据第二句话,“列”可以指定为:

  • 列名
  • 列别名
  • 列位置

CASE是一个“表达式”而不是列规范。该表达式未指定排序顺序列。表达式结果的值用于排序。

表达式的结果CASE WHEN Field1 IS NOT NULL THEN 0 END是一个整数(由于零整数常量),其值为 0 或NULL。表达式类型信息可以通过以下方式收集sys.dm_exec_describe_first_result_set

SELECT system_type_name, is_nullable
FROM sys.dm_exec_describe_first_result_set(N'SELECT CASE WHEN Field1 IS NOT NULL THEN 0 END FROM dbo.Table1',NULL,NULL);

+------------------+-------------+
| system_type_name | is_nullable |
+------------------+-------------+
| int              |           1 |
+------------------+-------------+
Run Code Online (Sandbox Code Playgroud)

使用稍微修改过的数据和有效的 CASE 表达式,您可以看到具有 NULL 值的行排在具有非空值的行之前,因为 CASE 表达式对于具有 NULL Field1 值的行返回 NULL,对于具有 NULL Field1 值的行返回零。非 NULL 值。

CREATE TABLE Table1(ID INT IDENTITY(1,1), Field1 INT, FieldSomethingElse VARCHAR(10));
INSERT INTO Table1 (Field1, FieldSomethingElse) VALUES (1, 'some');
INSERT INTO Table1 (Field1, FieldSomethingElse) VALUES (765, 'or');
INSERT INTO Table1 (Field1, FieldSomethingElse) VALUES (2, 'thing');
INSERT INTO Table1 (Field1, FieldSomethingElse) VALUES (NULL, 'another');
INSERT INTO Table1 (Field1, FieldSomethingElse) VALUES (NULL, 'thing');

SELECT *,CASE WHEN Field1 IS NOT NULL THEN 0 END AS ValueUsedForSorting
FROM Table1
ORDER BY 
   CASE WHEN Field1 IS NOT NULL 
     THEN 0 
   END;


+----+--------+--------------------+---------------------+
| ID | Field1 | FieldSomethingElse | ValueUsedForSorting |
+----+--------+--------------------+---------------------+
|  4 | NULL   | another            | NULL                |
|  5 | NULL   | thing              | NULL                |
|  1 | 1      | some               | 0                   |
|  3 | 765    | or                 | 0                   |
|  2 | 2      | thing              | 0                   |
+----+--------+--------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

我要补充的是,由于 NULL 无论如何都会在非 NULL 值之前排序,因此可以简单地按 Field1 进行排序以提供所需的排序行为,并且也许还可以利用列上的索引。与 CASE 表达式不同,此方法还将根据 Field1 值对非 NULL 值进行排序,而不是根据 CASE 表达式零值的未定义顺序(由于零值的关系)。

SELECT *,Field1 AS ValueUsedForSorting
FROM Table1
ORDER BY Field1;

+----+--------+--------------------+---------------------+
| ID | Field1 | FieldSomethingElse | ValueUsedForSorting |
+----+--------+--------------------+---------------------+
|  4 | NULL   | another            | NULL                |
|  5 | NULL   | thing              | NULL                |
|  1 | 1      | some               | 1                   |
|  3 | 2      | thing              | 2                   |
|  2 | 765    | or                 | 765                 |
+----+--------+--------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)


J.D*_*.D. 6

当您使用表达式(例如CASE)时,它不再按列名或列序排序,而是现在按排序。在本例中,您选择的值是 0(仅适用于非空Field1行),但也可以是 1、100、“Red”,甚至是IntFieldSomethingElse + 7

CASE如果你进一步构建你的表达式,你就会明白我的意思:

SELECT *
FROM Table1
ORDER BY 
   CASE 
       WHEN Field1 > 10 
           THEN 100 
        WHEN Field1 > 5
            THEN 200
        WHEN Field1 IS NOT NULL
            THEN 300
        ELSE 900
   END
Run Code Online (Sandbox Code Playgroud)

上面根据 的值是否Field1大于某个值对行进行半降序排序。它还有一个默认情况,即该ELSE子句,它将把所有行放在Field1 IS NULL结果的末尾。

显然,没有名称或序数为 100、200、300 或 900 的列,但上面的CASE表达式有效,因为 SQL Server按子句中满足该子句的行的对行进行排序。THENWHEN

当您使用 0 时,示例子句中也会发生同样的事情CASE,它只是对常量值 0 上的非空行进行排序。这显然在排序方面没有多大意义,除了所有非空行都将被排序一起(因为它们都将按相同的 0 值进行排序,因此它们在排序中的顺序将是不确定的)并且所有空行也将一起排序。