2010-07-16 18 views
8

Ich habe eine (ziemlich komplizierte) SQL-Anweisung, wo ich Daten aus vielen verschiedenen Tabellen auswählen, und mit einer schlechten alten Datenstruktur zu bewältigen, habe ich ein paar benutzerdefinierte Spalten, deren Werte auf Werten aus anderen Spalten basieren. Ich habe zur Zeit diese mit CASE Aussagen gelöst:Ungültiger Spaltenname Fehler in WHERE-Klausel, Spalte ausgewählt mit 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... 

ich alle Ergebnisse, die ich erwarten, wenn die Abfrage in MS SQL Server Management Studio ausgeführt wird, und die Spaltennamen aufgeführt sind, wie ich in meinem AS Klauseln angegeben haben. Aus irgendeinem Grund darf ich die bedingten Werte nicht in einer WHERE-Anweisung verwenden. Wenn ich

AND ChannelValue > Limit * p.Percentage/100 

am Ende der Abfrage hinzufügen, bekomme ich einen Fehler auf dieser Linie sagen

Msg 207, Ebene 16, Status 1, Zeile 152
Ungültiger Spaltenname ‚Channel‘

Warum ist das nicht erlaubt? Was soll ich stattdessen tun?

Antwort

11

Der einzige Teil der SQL-Anweisung, wo es gilt, einen Aliasnamen in der SELECT Liste deklariert zu verwenden ist die ORDER BY Klausel. Für andere Teile der Abfrage müssen Sie nur den gesamten CASE-Ausdruck wiederholen und dem Optimierer vertrauen, dass er identisch ist.

Wenn Sie SQL2005 + verwenden, können Sie ein CTE verwenden, um dieses Problem zu vermeiden, das manchmal die Lesbarkeit erleichtert.

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

Sie können den Spaltennamen ChannelValue nicht in der Where-Klausel auf derselben Ebene select verwenden.
Sie müssen diese ganze select in eine Unterabfrage stellen.

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

können Sie einen CTE verwenden - so etwas wie

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] 
Verwandte Themen