2010-07-16 12 views
8

Ho una (piuttosto complicata) istruzione SQL in cui seleziono i dati da molte diverse tabelle e per far fronte a una struttura di dati legacy errata, ho un paio di custom colonne che ottengono i loro valori in base ai valori di altre colonne. Ho attualmente risolto questo con CASE dichiarazioni:Errore nome colonna non valido nella clausola WHERE, colonna selezionata 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... 

ottengo tutti i risultati che mi aspetto quando si esegue la query in MS SQL Server Management Studio, ei nomi di colonna sono elencati come ho specificato nel mio AS clausole. Tuttavia, per qualche motivo non sono autorizzato a utilizzare i valori condizionali in un'istruzione WHERE. Se aggiungo

AND ChannelValue > Limit * p.Percentage/100 

al termine della query, ottengo un errore su quella linea dicendo

Msg 207, livello 16, stato 1, riga 152
nome di colonna non valido 'ChannelValue'

Perché non è consentito? Cosa dovrei fare invece?

risposta

11

L'unica parte della dichiarazione SQL in cui è valido per utilizzare un alias dichiarato nella lista SELECT è la clausola di ORDER BY. Per altre parti della query devi solo ripetere l'intera espressione CASE e fidarti dell'ottimizzatore per riconoscere che è lo stesso.

Se si utilizza SQL2005 + è possibile utilizzare un CTE per evitare questo problema che a volte aiuta con la leggibilità.

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

Non è possibile utilizzare il nome della colonna ChannelValue nella clausola where allo stesso livello select.
Dovrai inserire tutto il select in una sottoquery.

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

È possibile utilizzare un CTE - qualcosa come

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] 
Problemi correlati