根据别名列名进行过滤

20

我正在使用SqlServer 2005,并且我有一个我命名的列。

查询大概是这样的:

SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias
FROM myTable
WHERE myAlias IS NOT NULL

然而,这给我带来了错误:

"Invalid column name 'myAlias'."

有没有办法解决这个问题? 在过去,我通常将列定义包含在WHERE或HAVING部分中,但那些大多是简单的,比如COUNT(*)之类的。 我可以在这个临时查询中包含整个列定义,但如果出于某种原因我需要在生产查询中执行此操作,我更希望仅使用一次列定义,以便我不必同时更新两个部分(并在某些时候忘记其中一个)。

5个回答

19

你不能在where子句中像那样引用别名... 你必须要在WHERE中复制CASE语句,或者可以使用如下的子查询:

SELECT id, myAlias
FROM
(
    SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias
    FROM myTable
) data
WHERE myAlias IS NOT NULL

5
唉,我本希望它会更简单。 - Nathan Koop
我也是,其实应该有一个更通用的解决方案。 - Nick N.

6
使用公共表表达式(CTE)也是一种选择:
;with cte (id, myAlias)
 as (select id, case when <snip extensive column definition> end as myAlias 
      from myTable)
 select id, myAlias
  from cte
  where myAlias is not null

谢谢Philip,我不熟悉CTE,看起来它是一个临时视图。这个说法合理吗? - Nathan Koop

4
将相同的 CASE 语句放入 WHERE 子句中:
SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias
FROM myTable
WHERE CASE WHEN <snip extensive column definition> END IS NOT NULL

编辑

另一个选项是嵌套查询:

SELECT id, myAlias
FROM (
    SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias
    FROM myTable
) AS subTable
WHERE myAlias IS NOT NULL
(编辑:已删除HAVING选项,因为这是不正确的(感谢@OMG Ponies))

@OMG ponies:在SQL Server中试试。没有GROUP BY,基本上就和WHERE一样了... http://msdn.microsoft.com/en-us/library/ms180199%28SQL.90%29.aspx,所以Codesleuth的解决方案可能是正确的,而不需要使用派生表。 - gbn
@gbn:奇怪!我上班后一定会尝试。对不起,Codesleuth。 - OMG Ponies
@OMG ponies:至少这个有文档记录 :-) - gbn
我无法使其按照最初的意图工作;“OMG Ponies”在我看来是正确的 :) - Codesleuth
@OMG Ponies,@gbn,我无法像你在SQL2005中所述的那样使其工作,我猜你是在使用SQL2008? - Nathan Koop

1
把case语句放在where子句中。SQL Server会聪明地只评估一次,所以你并没有真正复制代码。
SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias
FROM myTable
WHERE CASE WHEN <snip extensive column definition> END IS NOT NULL

你可以将它包装在一个派生表中:

SELECT dt.id, dt.myAlias
    FROM (
          SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias
          FROM myTable
         ) dt
    WHERE dt.myAlias IS NOT NULL

无论如何,我尽量避免没有限制条件的派生表。您可以尝试一下,看它是否会影响性能。


@KM,我更担心的是我更新了一个CASE却忘记更新第二个。像你一样,我希望SQL Server会优化掉第二个调用。 - Nathan Koop

0

我最终创建了一个临时表来完成这个任务。以下是一些伪代码,以便您了解。这适用于复杂的连接,我只是在这里展示一个简单的情况。

--Check to see if the temp table already exists
If(OBJECT_ID('tempdb..#TempTable') Is Not Null)
Begin
    DROP TABLE #TempTable
End

--Create the temp table
CREATE TABLE #TempTable
{
     YourValues NVARCHAR(100)
}

--Insert your data into the temp table        
INSERT INTO #TempTable(YourValues)
SELECT yt.Column1 as YourColumnOne FROM YourTable yt

--Query the filtered data based on the aliased column    
SELECT * 
FROM #TempTable
WHERE YourColumnOne = 'DataToFilterOn'

--Don't forget to remove the temp table
DROP TABLE #TempTable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,