无法在where子句中使用临时列?

7
select  cast(de.ApprovalOrder AS VARCHAR(32)) 
            + cast(de.EntityCode AS VARCHAR(32)) 
            + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') as 'RowID' ,
            *
from    workflow.delegation_engine de
where   RowID <> NULL

当我尝试执行以下命令时,收到了错误提示:

Msg 207, Level 16, State 1, Line 13 Invalid column name 'RowID'.

请问如何引用这个临时列?我查找了之前的帖子,建议使用“having”,但似乎也不起作用。
2个回答

10

一个解决方案是对整个语句进行子选择,将where子句应用于其结果

select  *
from    (
          select  cast(de.ApprovalOrder AS VARCHAR(32)) 
                  + cast(de.EntityCode AS VARCHAR(32)) 
                  + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') as 'RowID'
                  , *
          from    workflow.delegation_engine de
        ) de 
where   de.RowID IS NOT NULL

另一种解决方案是在WHERE子句中重复整个条件语句

select  cast(de.ApprovalOrder AS VARCHAR(32)) 
        + cast(de.EntityCode AS VARCHAR(32)) 
        + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') as 'RowID' ,
        *
from    workflow.delegation_engine de
where   cast(de.ApprovalOrder AS VARCHAR(32)) 
        + cast(de.EntityCode AS VARCHAR(32)) 
        + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') IS NOT NULL

或者你可以测试每个单独的字段是否为NULL。

select  cast(de.ApprovalOrder AS VARCHAR(32)) 
        + cast(de.EntityCode AS VARCHAR(32)) 
        + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') as 'RowID' ,
        *
from    workflow.delegation_engine de
where   de.ApprovalOrder IS NOT NULL
        AND de.EntityCode IS NOT NULL

1
<> NULL会给操作者带来问题。我认为这不是预期的条件子句。 - user596075
3
作为Option2重构的更实用选择,Option3通常比Option1对优化器更有用。虽然可能感觉不太优美,但当它向优化器提供更多线索以减少执行计划时,它就具备可操作性和价值。 - MatBailie
我同意,但是对于具有多个人随时间跨度的大型查询来说,选项#3可能会很笨重 - 尽管如此,我肯定更喜欢它适用于这种规模的事情。 - Michael A
2
@Codingo - 现在我们进入了性能与维护之间的世界。让我们开始跳舞吧! - MatBailie
1
赞一个,因为你不仅纠正了一个简单的错误,还推荐了更好的解决方案。 - user596075

5

您需要在WHERE子句中使用express,或者将您的SELECT查询作为子查询使用,如下所示:

select *
from
(
    select  cast(de.ApprovalOrder AS VARCHAR(32))  
                + cast(de.EntityCode AS VARCHAR(32))  
                + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') as RowID, 
                * 
    from    workflow.delegation_engine de 
)
where RowID is not NULL 

或者,更加随意的(在我看来)做法是:
select  cast(de.ApprovalOrder AS VARCHAR(32))    
            + cast(de.EntityCode AS VARCHAR(32))    
            + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') as RowID,   
            *   
from    workflow.delegation_engine de   
where   cast(de.ApprovalOrder AS VARCHAR(32))    
            + cast(de.EntityCode AS VARCHAR(32))    
            + isnull(cast(de.DelegationCode AS VARCHAR(32)), '') is not null  

我会选择第一个解决方案。同时请注意,我已经更改了你的“WHERE”子句。
RowID <> NULL

To

RowID is not NULL

这是因为<> NULL永远不会被视为真。SQL Server使用ISIS NOT来测试NULL(即未知)。


1
+1 或者使用 CTE 而不是子查询。它们非常漂亮! - MatBailie
@Dems - 哦,请...去睡觉吧... ;) - Lieven Keersmaekers
@Dems 哈哈 :) 这是一个有趣的评论。不过我想知道性能差异会是多少。让我测试一下... - user596075
如果有的话,我会感到惊讶。对于这种情况,它只是(主观上)更易读。 - Lieven Keersmaekers
@Shark - 应该没有,子查询和CTE都只是内联视图。然而,Lieven的第三个选项可以根据索引减少派生到SARGable组件的推导,从而具有性能优势。 - MatBailie
@Dems 您是正确的,CTE和子查询具有完全相同的执行计划。 - user596075

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