我有以下查询,我想在表达式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'。
答案 0 :(得分:5)
您可以使用Common Table Expression:
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
也可以使用having来解决这个问题,但它不具备可读性或可维护性:
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
答案 1 :(得分:4)
问题是WHERE
和HAVING
子句在 SELECT
列表之前解析。这与聚合无关。如果你有一个非常简单的表达式会发生同样的事情,例如:
SELECT a = 1 + 2 WHERE a = 3;
SQL Server实际向后读取的图片:“对于a = 3的行,返回表达式1 + 2,并将其标记为a。”这不起作用,因为为了检查a = 3还不存在。我在dba.stackexchange.com上讨论了为什么这个问题在this answer和this answer上。还有其他一些值得一读的答案。
因此,您无法在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;
答案 2 :(得分:2)
要根据聚合函数筛选结果集,您需要将其包含在HAVING
子句中,而不是WHERE
子句中。
答案 3 :(得分:0)
聚合可能不会出现在WHERE子句中,除非它位于HAVING子句或选择列表中包含的子查询中,并且要聚合的列是外部引用