什么时候评估 CASE 语句?
When is the CASE statement evaluated?
我对 AdventureWorks2012 数据库有以下查询
SELECT productid,
productname,
unitprice,
CASE
WHEN unitprice < 20.0 THEN 'LOW'
WHEN unitprice < 40.0 THEN 'MEDIUM'
WHEN unitprice >= 40.0 THEN 'HIGH'
END pricerange
FROM Production.Products
ORDER BY
CASE
WHEN pricerange < 'LOW' THEN 1
WHEN pricerange < 'MEDIUM' THEN 2
WHEN pricerange >= 'HIGH' THEN 3
END ASC
GO
ORDER BY
发生在SELECT
语句之后,但是pricerange列名无法访问?我假设 SELECT
语句中的价格范围是在调用 ORDER BY
之后计算的?这是为什么?
SQL 是一种声明性语言,而不是命令性语言。执行顺序未定义,而且并不总是相同。
无论如何,执行顺序并不重要。重点是 scope - 并且 pricerange
不在该 select 语句的任何范围内。与其考虑代码行出现的顺序(如命令式编程),不如考虑每个表达式如何包裹另一个表达式。
在这种情况下,您正在做这样的事情:
Select(OrderBy(From(Products), ...), ...)
您有两种解决方法 - 一种选择是使用与您在 select 中使用的顺序相同的大小写(别担心,引擎足够聪明,不会这样做工作两次)。第二种是将您的查询包装在另一个执行实际排序的查询中:
select * from
(
SELECT productid,
productname,
unitprice,
CASE
WHEN unitprice < 20.0 THEN 'LOW'
WHEN unitprice < 40.0 THEN 'MEDIUM'
WHEN unitprice >= 40.0 THEN 'HIGH'
END pricerange
FROM Production.Products
)
ORDER BY
CASE
WHEN pricerange < 'LOW' THEN 1
WHEN pricerange < 'MEDIUM' THEN 2
WHEN pricerange >= 'HIGH' THEN 3
END ASC
但请记住,您在这里处理的是表达式树,而不是命令列表。您是在描述您想要什么,而不是如何执行。 如何 是执行引擎的工作。
最后,执行引擎可能会为查询的两种变体制定相同的执行计划——它们并没有真正的不同;例如,虽然 NULL 周围可能存在一些极端情况,但我不确定。
SQL服务器解释逻辑处理documentation中查询的顺序。
- FROM
- ON
- JOIN
- WHERE
- GROUP BY
- WITH CUBE or WITH ROLLUP
- HAVING
- SELECT
- DISTINCT
- ORDER BY
- TOP
请注意,这是 合乎逻辑的。实际上,这意味着排序在查询的编译阶段主要用于确定引用的名称。另请注意,该列表是关键字和子句的奇怪组合(ON
、WITH
、DISTINCT
和 TOP
不是 SQL 子句)。
至于你的查询,pricerange
的定义是由SELECT
中的逻辑决定的。然后在 ORDER BY
中进一步使用它来获得您想要的顺序。这是处理的逻辑描述。
实际上,我希望 SQL 服务器在扫描数据时计算 pricerange
和排序优先级(SQL 服务器通过在读取数据)。 pricerange
计算进入最终结果集。订购件仅供 ORDER BY
.
使用
我对 AdventureWorks2012 数据库有以下查询
SELECT productid,
productname,
unitprice,
CASE
WHEN unitprice < 20.0 THEN 'LOW'
WHEN unitprice < 40.0 THEN 'MEDIUM'
WHEN unitprice >= 40.0 THEN 'HIGH'
END pricerange
FROM Production.Products
ORDER BY
CASE
WHEN pricerange < 'LOW' THEN 1
WHEN pricerange < 'MEDIUM' THEN 2
WHEN pricerange >= 'HIGH' THEN 3
END ASC
GO
ORDER BY
发生在SELECT
语句之后,但是pricerange列名无法访问?我假设 SELECT
语句中的价格范围是在调用 ORDER BY
之后计算的?这是为什么?
SQL 是一种声明性语言,而不是命令性语言。执行顺序未定义,而且并不总是相同。
无论如何,执行顺序并不重要。重点是 scope - 并且 pricerange
不在该 select 语句的任何范围内。与其考虑代码行出现的顺序(如命令式编程),不如考虑每个表达式如何包裹另一个表达式。
在这种情况下,您正在做这样的事情:
Select(OrderBy(From(Products), ...), ...)
您有两种解决方法 - 一种选择是使用与您在 select 中使用的顺序相同的大小写(别担心,引擎足够聪明,不会这样做工作两次)。第二种是将您的查询包装在另一个执行实际排序的查询中:
select * from
(
SELECT productid,
productname,
unitprice,
CASE
WHEN unitprice < 20.0 THEN 'LOW'
WHEN unitprice < 40.0 THEN 'MEDIUM'
WHEN unitprice >= 40.0 THEN 'HIGH'
END pricerange
FROM Production.Products
)
ORDER BY
CASE
WHEN pricerange < 'LOW' THEN 1
WHEN pricerange < 'MEDIUM' THEN 2
WHEN pricerange >= 'HIGH' THEN 3
END ASC
但请记住,您在这里处理的是表达式树,而不是命令列表。您是在描述您想要什么,而不是如何执行。 如何 是执行引擎的工作。
最后,执行引擎可能会为查询的两种变体制定相同的执行计划——它们并没有真正的不同;例如,虽然 NULL 周围可能存在一些极端情况,但我不确定。
SQL服务器解释逻辑处理documentation中查询的顺序。
- FROM
- ON
- JOIN
- WHERE
- GROUP BY
- WITH CUBE or WITH ROLLUP
- HAVING
- SELECT
- DISTINCT
- ORDER BY
- TOP
请注意,这是 合乎逻辑的。实际上,这意味着排序在查询的编译阶段主要用于确定引用的名称。另请注意,该列表是关键字和子句的奇怪组合(ON
、WITH
、DISTINCT
和 TOP
不是 SQL 子句)。
至于你的查询,pricerange
的定义是由SELECT
中的逻辑决定的。然后在 ORDER BY
中进一步使用它来获得您想要的顺序。这是处理的逻辑描述。
实际上,我希望 SQL 服务器在扫描数据时计算 pricerange
和排序优先级(SQL 服务器通过在读取数据)。 pricerange
计算进入最终结果集。订购件仅供 ORDER BY
.