我正在阅读一本SQL书籍,问题之一是:
针对Sales.Customers表编写查询,该表为每个客户返回客户ID和区域。按区域对输出中的行进行按区域排序,其中NULL标记排在最后(在非NULL值之后)。请注意,T-SQL中NULL标记的默认排序行为是首先排在(非NULL值之前)。 >
答案是:
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之前?
答案 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