我有以下查询,我想在Percentage
包含聚合的表达式上使用 where 子句:
SELECT Percentage = CONVERT(DECIMAL(10,1),100 - COUNT(some_irrelevant_column))
FROM Product P INNER JOIN Item PD
ON PD.ProductId = P.ProductId
WHERE Percentage < 50;
这会产生以下错误:
列名“百分比”无效。
我有以下查询,我想在Percentage
包含聚合的表达式上使用 where 子句:
SELECT Percentage = CONVERT(DECIMAL(10,1),100 - COUNT(some_irrelevant_column))
FROM Product P INNER JOIN Item PD
ON PD.ProductId = P.ProductId
WHERE Percentage < 50;
这会产生以下错误:
列名“百分比”无效。
您可以使用公用表表达式:
with cte as (
select CONVERT(DECIMAL(10,1),100 - (CAST(COUNT(DISTINCT case when PD.ExceptionCode != ' ' then PD.Id END) as float)/CAST(COUNT(PD.Id) as float)*100)) as Percentage
from Product as P
inner join Item as PD on PD.ProductId = P.ProductId
)
select Percentage from cte where Percentage < 50
可以使用subquery,但对我来说 CTE 更具可读性
select *
from (
select CONVERT(DECIMAL(10,1),100 - (CAST(COUNT(DISTINCT case when PD.ExceptionCode != ' ' then PD.Id END) as float)/CAST(COUNT(PD.Id) as float)*100)) as Percentage
from Product as P
inner join Item as PD on PD.ProductId = P.ProductId
) as A
where A.Percentage < 50
也可以使用 have 来解决这个问题,但它的可读性或可维护性不强:
select CONVERT(DECIMAL(10,1),100 - (CAST(COUNT(DISTINCT case when PD.ExceptionCode != ' ' then PD.Id END) as float)/CAST(COUNT(PD.Id) as float)*100)) as Percentage
from Product as P
inner join Item as PD on PD.ProductId = P.ProductId
having CONVERT(DECIMAL(10,1),100 - (CAST(COUNT(DISTINCT case when PD.ExceptionCode != ' ' then PD.Id END) as float)/CAST(COUNT(PD.Id) as float)*100)) < 50
问题是WHERE
andHAVING
子句都在列表之前被解析。SELECT
这与聚合无关。如果您有一个非常简单的表达式,也会发生同样的事情,例如:
SELECT a = 1 + 2 WHERE a = 3;
想象一下 SQL Server 实际上是反向读取的:“对于 a = 3 的行,返回表达式 1 + 2,并将其标记为 a。” 这不起作用,因为 a 尚不存在,以便检查 a = 3。我稍微谈谈为什么这是这个答案以及dba.stackexchange.com 上的这个答案(那里还有一些其他答案也值得一读)。
因此,您不能在SELECT
列表中创建别名,然后在其他子句中引用别名(ORDER BY
这是唯一可行的,即使在那里您也会发现异常)。解决方法是使用子查询或 CTE:
SELECT a FROM (SELECT 1 + 2) AS x(a) WHERE a = 3;
;WITH x(a) AS (SELECT 1 + 2) SELECT a FROM x WHERE a = 3;
或者重复表达式(通常是不可取的):
SELECT a = 1 + 2 WHERE 1 + 2 = 3;
要基于聚合函数过滤结果集,您需要将其包含在HAVING
子句中,而不是WHERE
子句中。
聚合可能不会出现在 WHERE 子句中,除非它位于 HAVING 子句或选择列表中包含的子查询中,并且被聚合的列是外部引用