2010-07-16 60 views
8

我有一個(非常複雜的)SQL語句,我從很多不同的表中選擇數據,爲了應對不良的遺留數據結構,我有一些自定義根據其他列的值獲取其值的列。我已經與目前陳述CASE解決了這個:在WHERE子句中,無效的列名錯誤使用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... 

我得到的所有執行在MS SQL Server Management Studio中查詢時,列名被列爲我在AS子句指定我所期望的結果。但是,由於某種原因,我不允許在WHERE語句中使用條件值。如果我在查詢的末尾添加

AND ChannelValue > Limit * p.Percentage/100 

,我得到一個錯誤在該行稱

消息207,級別16,狀態1,行152
無效的列名稱ChannelValue「

爲什麼不允許這樣做?我該怎麼做呢?

回答

11

SQL語句它是有效的使用在SELECT列表中聲明一個別名的只有部分是ORDER BY條款。對於查詢的其他部分,您只需重複整個CASE表達式並相信優化器識別它是相同的。

如果您使用的是SQL2005 +,則可以使用CTE來避免此問題,這有助於提高可讀性。

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

不能在同一select級別的where子句中使用ChannelValue列名。
你將不得不把這整個select在一個子查詢。

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

您可以使用CTE - 像

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]