在WHERE子句中引用别名表达式

时间:2013-08-14 17:19:37

标签: sql sql-server sql-server-2008 tsql

我有以下查询,我想在表达式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'。

4 个答案:

答案 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)

问题是WHEREHAVING子句在 SELECT列表之前解析。这与聚合无关。如果你有一个非常简单的表达式会发生同样的事情,例如:

SELECT a = 1 + 2 WHERE a = 3;

SQL Server实际向后读取的图片:“对于a = 3的行,返回表达式1 + 2,并将其标记为a。”这不起作用,因为为了检查a = 3还不存在。我在dba.stackexchange.com上讨论了为什么这个问题在this answerthis 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子句或选择列表中包含的子查询中,并且要聚合的列是外部引用