2010-07-16 17 views
8

Tengo una declaración de SQL (bastante complicada) en la que selecciono datos de muchas tablas diferentes, y para lidiar con una estructura de datos heredada, tengo un par de personalizados columnas que obtienen sus valores basados ​​en valores de otras columnas. He resuelto actualmente esto con CASE declaraciones:Error de nombre de columna inválido en la cláusula WHERE, columna seleccionada con CASE

SELECT 
    ..., 
    CASE channel 
     WHEN 1 THEN channel_1 
     WHEN 2 THEN channel_2 
     ... 
     ELSE 0 
    END AS ChannelValue, 
    CASE channelu 
     WHEN 1 THEN channelu_1 
     WHEN 2 THEN channelu_2 
     ... 
     ELSE '0' 
    END AS ChannelWithUnit, 
    ... 
FROM 
    ... 
--rest of statement continues with multiple joins and where/and clauses... 

consigo todos los resultados que cabe esperar cuando se ejecuta la consulta en MS SQL Server Management Studio, y los nombres de columna se enumeran como he indicado en mis AS cláusulas. Sin embargo, por alguna razón, no estoy autorizado a usar los valores condicionales en una declaración WHERE. Si añado

AND ChannelValue > Limit * p.Percentage/100 

al final de la consulta, me sale un error en esa línea diciendo

Msg 207, nivel 16, estado 1, línea 152
nombre de columna no válido 'ChannelValue'

¿Por qué no se permite? ¿Qué debería hacer?

Respuesta

11

La única parte de la instrucción SQL donde es válido utilizar un alias declararse en la lista SELECT es la cláusula ORDER BY. Para otras partes de la consulta, solo tiene que repetir toda la expresión de CASE y confiar en que el optimizador reconozca que es la misma.

Si está en SQL2005 + puede usar un CTE para evitar este problema que a veces ayuda a la legibilidad.

WITH YourQuery As 
(

SELECT 
    Limit, 
    Percentage, 
    CASE channel 
     WHEN 1 THEN channel_1 
     WHEN 2 THEN channel_2 
     ... 
     ELSE 0 
    END AS ChannelValue, 
    CASE channelu 
     WHEN 1 THEN channelu_1 
     WHEN 2 THEN channelu_2 
     ... 
     ELSE '0' 
    END AS ChannelWithUnit, 
    ... 
FROM 
) 

select ... 
FROM YourQuery WHERE 
ChannelValue > Limit * Percentage/100 
7

No se puede usar ChannelValue nombre de columna en la cláusula where en el mismo nivel select.
Tendrá que poner todo este select en una subconsulta.

select .... 
from 
( 
your select query 
) as innerSelect 
where ChannelValue > Limit * p.Percentage/100 
2

Puede utilizar un CTE - algo así como

WITH CTE AS 
(
SELECT 
    ..., 
    CASE channel 
     WHEN 1 THEN channel_1 
     WHEN 2 THEN channel_2 
     ... 
     ELSE 0 
    END AS ChannelValue, 
    CASE channelu 
     WHEN 1 THEN channelu_1 
     WHEN 2 THEN channelu_2 
     ... 
     ELSE '0' 
    END AS ChannelWithUnit, 
    ... 
FROM 
) 
SELECT * 
FROM CTE 
WHERE ChannelValue > Limit * p.Percentage/100 
-2
-- SOMETHING FROM ADVENTURE WORKS THIS WORKS AS THE ABOVE POSTER 
--- USING 'WITH CTE AS' 
-- MY ANSWER TO A QUERY 

WITH CTE AS 
(
SELECT HE.Gender AS [GENDER], HE.HireDate AS [HIREDATE],  HE.BirthDate AS [BIRTHDATE], 
CASE 
WHEN DATEPART(YY,[BIRTHDATE]) BETWEEN 1962 AND 1970 AND [GENDER] = 'M' AND DATEPART(YY,[HIREDATE]) > 2001 THEN 'MALE' 
WHEN DATEPART(YY,[BIRTHDATE]) BETWEEN 1972 AND 1975 AND [GENDER] = 'F' AND DATEPART(YY,[HIREDATE]) BETWEEN 2001 AND 2002 THEN 'FEMALE' 
ELSE 'NOTREQUIRED' 
END AS [RESULT] 
FROM [HumanResources].[Employee] AS HE 
) 
SELECT * 
FROM CTE 
WHERE [RESULT] <> 'NOTREQUIRED' -- GOT THIS TOO WORK NO FEMALES IN RESULT 
ORDER BY [RESULT] 
Cuestiones relacionadas