【问题标题】:How do I use alias in where clause? [duplicate]如何在 where 子句中使用别名? [复制]
【发布时间】:2012-10-13 10:02:54
【问题描述】:

可能重复:
Referring to a Column Alias in a WHERE Clause

   SELECT
Trade.TradeId, 
Isnull(Securities.SecurityType,'Other') SecurityType, 
TableName,
CASE 
WHEN 
SecurityTrade.SecurityId IS NOT NULL  
THEN 
SecurityTrade.SecurityId
ELSE 
Trade.SecurityId
END AS PricingSecurityID,
sum(Trade.Quantity)OVER(Partition by Securities.SecurityType, SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
--added porfolio id for Getsumofqantity
Trade.PortfolioId,

Trade.Price,
case
when (Buy = 1 and Long = 1) then 1
when (Buy = 0 and Long = 0) then 1
else 0
end Position
from
Fireball_Reporting..Trade

where porfolioid =5 and Position =1   

我想在 where 子句中使用 Position =1,它是 case 的别名

case
when (Buy = 1 and Long = 1) then 1
when (Buy = 0 and Long = 0) then 1
else 0
end Position

如何在 where 子句中使用它?

我试过 zo 直接在 where 子句中使用那个 CASE 语句,但是失败了。

WHERE Trade.SecurityId = @SecurityId AND PortfolioId = @GHPortfolioID AND
                (case when (Buy = 1 and Long = 1) then 1 when (Buy = 0 and Long = 0) then 1 else 0 end Position = 1)

【问题讨论】:

  • 你不能,除非你在外部查询中添加另一个选择并检查 postion = 1。
  • 您使用的是什么 SQL 语言?
  • sql server 2008 中的 T SQL

标签: sql sql-server qtsql


【解决方案1】:

SQL-Server docs 说:

column_alias 可以在 ORDER BY 子句中使用,但它不能在 WHERE、GROUP BY 或 HAVING 子句中使用

MySQL doc 中类似,它说:

标准 SQL 不允许在 WHERE 子句中引用列别名。施加此限制是因为在评估 WHERE 子句时,可能尚未确定列值。

MySQL中你至少可以reuse aliases in the SELECT clause

【讨论】:

    【解决方案2】:

    你不能,不能直接。

    但是,如果您将整个查询包装在一个子查询中,它就可以正常工作。

    SELECT
      *
    FROM
    (
      SELECT
        Trade.TradeId, 
        Isnull(Securities.SecurityType,'Other') SecurityType, 
        TableName,
        CASE 
          WHEN SecurityTrade.SecurityId IS NOT NULL THEN SecurityTrade.SecurityId
                                                    ELSE Trade.SecurityId
        END AS PricingSecurityID,
        sum(Trade.Quantity)OVER(Partition by Securities.SecurityType,
        SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
        --added porfolio id for Getsumofqantity
        Trade.PortfolioId,
        Trade.Price,
        case
          when (Buy = 1 and Long = 1) then 1
          when (Buy = 0 and Long = 0) then 1
                                      else 0
        end Position
      from
        Fireball_Reporting..Trade
      where
        porfolioid = 5
    )
      AS data
    WHERE
      Position = 1   
    

    这意味着您不需要在WHERE 子句中重复CASE 语句。 (可维护和干燥)。

    它也是一种结构,它允许优化器就好像只是在WHERE子句中重复了你自己。

    它对于其他 RDBMS 也非常可移植。


    在 SQL Server 中,您还有另一个选择...

    SELECT
      Trade.TradeId, 
      Isnull(Securities.SecurityType,'Other') SecurityType, 
      TableName,
      CASE 
        WHEN SecurityTrade.SecurityId IS NOT NULL THEN SecurityTrade.SecurityId
                                                  ELSE Trade.SecurityId
      END AS PricingSecurityID,
      sum(Trade.Quantity)OVER(Partition by Securities.SecurityType,
      SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
      --added porfolio id for Getsumofqantity
      Trade.PortfolioId,
      Trade.Price,
      position.val AS Position
    from
      Fireball_Reporting..Trade
    CROSS APPLY
    (
      SELECT
        case
          when (Buy = 1 and Long = 1) then 1
          when (Buy = 0 and Long = 0) then 1
                                      else 0
        end AS val
    )
      AS position
    where
      porfolioid = 5
      AND position.val = 1
    

    【讨论】:

    • Juergen 的回答和您的回答与“..评估 WHERE 子句时,列值可能尚未确定”这一事实有关。但是由于您使用的是子查询。
    • 子查询是一个绝妙的解决方案!
    【解决方案3】:

    您不能直接执行此操作...但您可以在其周围添加一个额外的选择并使用 where 子句:

        select * from 
       (   SELECT
       Trade.TradeId, 
       Isnull(Securities.SecurityType,'Other') SecurityType, 
       TableName,
       CASE 
       WHEN 
       SecurityTrade.SecurityId IS NOT NULL  
       THEN 
       SecurityTrade.SecurityId
       ELSE 
       Trade.SecurityId
       END AS PricingSecurityID,
       sum(Trade.Quantity)OVER(Partition by Securities.SecurityType,       SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
        --added porfolio id for Getsumofqantity
        Trade.PortfolioId,
         Trade.Price,
         case
         when (Buy = 1 and Long = 1) then 1
         when (Buy = 0 and Long = 0) then 1
         else 0
        end Position
        from
        Fireball_Reporting..Trade
        where porfolioid =5 and Position =1 
        )x
        where x.position = 1
    

    【讨论】:

      【解决方案4】:

      我可能遗漏了一些东西,但这肯定会涵盖它:

      WHERE (Buy = 1 and Long = 1) OR (Buy = 0 and Long = 0)

      【讨论】:

      • 确实如此。但是“不要重复自己”(DRY)是一个基本原则,它极大地帮助维护和调试。因此,非常希望能够多次引用一个计算。
      猜你喜欢
      • 2011-04-20
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 2010-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多