9

我有一个(相当复杂的)SQL 语句,我从许多不同的表中选择数据,并且为了应对糟糕的遗留数据结构,我有几个自定义列,它们根据来自其他列的值获取它们的值。我目前已经通过以下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”

为什么不允许这样做?我应该怎么做?

4

4 回答 4

12

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
于 2010-07-16T12:53:54.050 回答
7

您不能ChannelValue在同一select级别的 where 子句中使用列名。
您必须将其全部select放在子查询中。

select ....
from 
( 
your select query
) as innerSelect
where ChannelValue > Limit * p.Percentage / 100
于 2010-07-16T12:50:49.517 回答
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 
于 2010-07-16T12:54:35.750 回答
-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]
于 2017-04-13T18:46:15.143 回答