Sql 在 where 子句中抛出聚合错误

Sql throwing up error on aggregate in where clause

SELECT A.A1, A.B2, A.C2, 
(select AVG(X1.parm) 
 from (VALUES (A.KK1),(A.KK2)) as X1(parm) 
 where X1.parm >110 and X1.parm is not NULL
) as observed           
FROM Table A
WHERE observed > 200

这是抛出错误:无效的列名'observed' 为什么?

您不能在同一范围内的 where 子句中重复使用 select 子句中定义的别名。

此处的解决方法是横向连接:

select a.a1, a.b2, a.c2, x.observed
from table a
cross apply (
    select avg(x.parm) observed
    from (values (a.kk1),(a.kk2)) as x(parm) 
    where x.parm > 110 and x.parm is not null
) x
where x.observed > 200

您不能在 WHERE 中通过别名引用列,因为 SELECTWHERE 之后解析。参见 Logical Processing Order of the SELECT statement

将子查询移动到 FROM:

SELECT A.A1,
       A.B2,
       A.C2,
       C.observed
FROM [Table] A
     CROSS APPLY (SELECT AVG(X1.parm) AS observed
                  FROM (VALUES (A.KK1),
                               (A.KK2)) X1 (parm)
                  WHERE X1.parm > 110
                    AND X1.parm IS NOT NULL) C
WHERE C.observed > 200;

如果子查询可能没有 return 任何行,则使用 OUTER APPLY 代替。

正如其他关于逻辑查询处理的回答中提到的,WHERE 子句对新的派生列不可见。

Read more on Logical query processing

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE/ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP
  12. OFFSET/FETCH

如果要引用专栏,可以有多种方式。下面给出了一些方法:

方式 1:利用 CTE

;WITH CTE_Table1 AS
(
SELECT A.A1, A.B2, A.C2, 
(select AVG(X1.parm) 
 from (VALUES (A.KK1),(A.KK2)) as X1(parm) 
 where X1.parm >110 and X1.parm is not NULL
) as observed           
FROM Table A
)
SELECT * FROM cte_Table1
WHERE observed > 200

方式二:使用派生table

SELECT * FROM 
(SELECT A.A1, A.B2, A.C2, 
(select AVG(X1.parm) 
 from (VALUES (A.KK1),(A.KK2)) as X1(parm) 
 where X1.parm >110 and X1.parm is not NULL
) as observed           
FROM Table A) as derived_Table1
WHERE observed > 200

我相信您在 SQL Server 2008 中有常见的 table 表达式,那么为什么不简单地将现有查询包装在 WITH 中以便您的别名可用?:

WITH cte AS (
SELECT A.A1, A.B2, A.C2, 
(select AVG(X1.parm) 
 from (VALUES (A.KK1),(A.KK2)) as X1(parm) 
 where X1.parm >110 and X1.parm is not NULL
) as observed           
FROM Table A
)
SELECT * FROM cte
WHERE observed > 200

除非我遗漏了什么?