简体   繁体   中英

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

This is throwing up error: Invalid column name 'observed' why?

You can't reuse an alias defined in the select clause in the where clause in the same scope.

A workaround here is a lateral join:

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

You can't reference a column by its alias in the WHERE , as the SELECT is parsed after the WHERE . See Logical Processing Order of the SELECT statement .

Move the subquery into the 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;

If the subquery might not return any rows, then use an OUTER APPLY instead.

As mentioned in other answer about logical query processing, the WHERE clause does not have visbibility to the new derived column.

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

If you want to refer to the column, then you can do in multiple ways. Some approaches are given below:

Way 1: Leverage 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

Way 2: Using derived 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

I believe you have common table expressions with SQL Server 2008, so why not simply wrap your existing query in a WITH so that your alias becomes available?:

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

Unless there's something I'm missing?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM