订购后的用例

时间:2019-04-17 10:18:43

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

我正在阅读一本SQL书籍,问题之一是:

针对Sales.Customers表编写查询,该表为每个客户返回客户ID和区域。按区域对输出中的行进行按区域排序,其中NULL标记排在最后(在非NULL值之后)。请注意,T-SQL中NULL标记的默认排序行为是首先排在(非NULL值之前)。 >

enter image description here

答案是:

SELECT custid, region
FROM Sales.Customers
ORDER BY
 CASE WHEN region IS NULL THEN 1 ELSE 0 END, region;

我有点主意,但仍然感到困惑,让我们以 custid = 9 为例进行记录: 由于客户9的区域为空,因此在cstatement返回1的情况下,查询如下:

ORDER BY 1, region

等效于:

ORDER BY custid, region  --because custid is the first column

那么,如何使客户9不在客户10之前(输出中的第二条记录)?是不是输出首先需要按监护权排序,所以9在10之前?

5 个答案:

答案 0 :(得分:2)

您的解释不正确。 1是一个简单的数字,而不是列引用。

查询等同于:

SELECT custid, region
FROM (SELECT c.*,
             (CASE WHEN region IS NULL THEN 1 ELSE 0 END) as region_is_null
      FROM Sales.Customers c
     ) c
ORDER BY region_is_null, region;

这是ORDER BY中数字的重要区别。表达式:

ORDER BY 1

是指第一列。但是,

ORDER BY 1 + 0

仅仅是返回常量1的数字表达式-并在SQL Server中导致错误(不允许在ORDER BY中使用常量)。

答案 1 :(得分:1)

  

所以查询就像

ORDER BY 1, region

不,这是不正确的。表达式CASE WHEN region IS NULL THEN 1 ELSE 0 END按行计算; 1是一个值而不是列位置。 ORDER BY中的列位置只能指定为文字而不是表达式。所以这个:

custid    region
8         NULL
9         NULL
10        BC
42        BC
45        CA

成为:

custid    region    case...
8         NULL      1
9         NULL      1
10        BC        0
42        BC        0
45        CA        0

排序后的结果可能是:

custid    region    case...
10        BC        0
42        BC        0
45        CA        0
8         NULL      1
9         NULL      1

或者:

custid region case...
42     BC     0
10     BC     0
45     CA     0
9      NULL   1
8      NULL   1

答案 2 :(得分:1)

ORDER BY CASE
           WHEN region IS NULL THEN
             1
           ELSE
             0
         END,
         region

不等于

ORDER BY 1,
         region

因为在第二列中,要作为排序依据的第一列始终是常数,而在第一列中,列可以根据CASE进行更改。

ORDER BY 1,
         region

也不等同于

ORDER BY custid,
         region

再次1是常数,但custid是可变的。

什么

ORDER BY CASE
           WHEN region IS NULL THEN
             1
           ELSE
             0
         END,
         region

这样做是根据region的内容“生成”一个新列进行排序。当1为空region时,该新列将获得0。如果您想象表格中的这一新列看起来像

custid | region | new column
...
10     | BC     | 0
...
9      | NULL   | 1
...

现在,如果按新列和区域对ID进行排序,则ID为10的客户比ID为9的客户要早,因为ID为10的客户的价值较低新列-0与ID为1的客户的9相对。

答案 3 :(得分:0)

您可以尝试以下操作-在您的情况下,先是0,然后是1,因此您需要更改值的顺序,或者如果您不想更改值,则可以执行desc顺序

SELECT custid, region
FROM Sales.Customers
ORDER BY
 CASE WHEN region IS NULL THEN 0 ELSE 1 END, region

答案 4 :(得分:0)

这种想法是使用CASE语句创建一个计算虚拟列,以将null标记为0,将null标记为1,然后进行相应的排序。

如果在order by子句中使用0,则会收到错误消息,因为在位置0处没有列,而且如果对选定的列进行重新排序,结果也将相同。 因此case语句的输出不是列的位置,而是计算所得的列。

customer_id        region      marker
not important      if null        0