【问题标题】:Sql Case When query查询时的Sql案例
【发布时间】:2013-06-11 08:15:22
【问题描述】:

我发现“CASE WHEN”语句对我的查询非常有用。 但这是我的查询(仅选择):

SELECT  dbo.ARCHIVE.SYSTEM_KEY AS PROTOCOLLO, 
        CASE dbo.ARCHIVEDEST.ERR_ID WHEN 0 THEN 'OK' ELSE 'KO' END AS ESITO, 
        CASE WHEN dbo.ARCHIVEDEST.XMODE IN ('R', 'K', 'H') THEN 'RX' ELSE 'TX' END AS 'T/R', 
        CASE 'T/R' WHEN 'TX' THEN CONTACTORIGIN.address ELSE CONTACTDESTINATION.address END AS Utente, 

问题出在第三个 Case 语句上,因为不评估先前的“T/R”查询(对于所有记录,它返回“CONTACTORIGIN.address”。 有可能这样做吗?还是我走错路了?

【问题讨论】:

    标签: sql sql-server sql-server-2008 tsql select


    【解决方案1】:

    使用子查询定义T/R别名;

    SELECT  *
    ,       CASE 'T/R' WHEN 'TX' THEN CONTACTORIGIN.address ELSE CONTACTDESTINATION.address 
                END AS Utente
    FROM    (
            SELECT  CASE dbo.ARCHIVEDEST.ERR_ID WHEN 0 THEN 'OK' ELSE 'KO' END AS ESITO
            ,       CASE WHEN dbo.ARCHIVEDEST.XMODE IN ('R', 'K', 'H') THEN 'RX' ELSE 'TX' 
                        END AS 'T/R'
            FROM    dbo.ARCHIVE.SYSTEM_KEY AS PROTOCOLLO
            ) as SubQueryAlias
    

    【讨论】:

      【解决方案2】:

      你必须重复测试:

      SELECT  dbo.ARCHIVE.SYSTEM_KEY AS PROTOCOLLO, 
              CASE dbo.ARCHIVEDEST.ERR_ID WHEN 0 THEN 'OK' ELSE 'KO' END AS ESITO, 
              CASE WHEN dbo.ARCHIVEDEST.XMODE IN ('R', 'K', 'H') THEN 'RX' ELSE 'TX' END AS 'T/R', 
              CASE CASE WHEN dbo.ARCHIVEDEST.XMODE NOT IN ('R', 'K', 'H') THEN CONTACTORIGIN.address ELSE CONTACTDESTINATION.address END AS Utente, 
      

      或者你可以做一个子查询:

      SELECT PROTOCOLLO, ESITO, [T/R],
          CASE WHEN [T/R] = 'TX' THEN CONTACTORIGIN.address ELSE CONTACTDESTINATION.address END AS Utente
      FROM
      (SELECT  dbo.ARCHIVE.SYSTEM_KEY AS PROTOCOLLO, 
              CASE dbo.ARCHIVEDEST.ERR_ID WHEN 0 THEN 'OK' ELSE 'KO' END AS ESITO, 
              CASE WHEN dbo.ARCHIVEDEST.XMODE IN ('R', 'K', 'H') THEN 'RX' ELSE 'TX' END AS [T/R], 
      ) s
      

      【讨论】:

      • 也可以考虑使用子选择或视图。
      • 只是在编辑我的答案添加子查询,好点:)
      【解决方案3】:

      如果您不想重复您的案例陈述,您有两个选择,第一个是将其中一个移动到子查询中,即

      SELECT  PROTOCOLLO,
              ESITO,
              [T/R],
              CASE [T/R] WHEN 'TX' THEN CONTACTORIGIN.address ELSE CONTACTDESTINATION.address END AS Utente
      FROM    (   SELECT  dbo.ARCHIVE.SYSTEM_KEY AS PROTOCOLLO, 
                          CASE dbo.ARCHIVEDEST.ERR_ID WHEN 0 THEN 'OK' ELSE 'KO' END AS ESITO, 
                          CASE WHEN dbo.ARCHIVEDEST.XMODE IN ('R', 'K', 'H') THEN 'RX' ELSE 'TX' END AS 'T/R'
                  FROM    ....
              ) SubQuery
      

      或者您可以将您的 CASE 声明移到 CROSS APPLY 中:

      SELECT  dbo.ARCHIVE.SYSTEM_KEY AS PROTOCOLLO, 
              CASE dbo.ARCHIVEDEST.ERR_ID WHEN 0 THEN 'OK' ELSE 'KO' END AS ESITO, 
              'T/R', 
              CASE [T/R] WHEN 'TX' THEN CONTACTORIGIN.address ELSE CONTACTDESTINATION.address END AS Utente
      FROM    ...
              CROSS APPLY
              (   SELECT  CASE WHEN dbo.ARCHIVEDEST.XMODE IN ('R', 'K', 'H') THEN 'RX' ELSE 'TX' END AS 'T/R'
              ) tx
      

      【讨论】:

        【解决方案4】:

        当您在 SELECT 子句中计算列的值时,您不能访问在同一 SELECT 子句中计算的任何其他计算值 - 因为(根据 SQL 标准)列是被并行计算(它们可能不是,但假设某些实现这样做),因此计算值尚不可用。

        您可以将“较早”的计算放在子查询或 CTE 中:

        SELECT *,
            CASE [T/R] WHEN 'TX' THEN CONTACTORIGIN.address ELSE CONTACTDESTINATION.address END AS Utente
        FROM (
            SELECT  dbo.ARCHIVE.SYSTEM_KEY AS PROTOCOLLO, 
                CASE dbo.ARCHIVEDEST.ERR_ID WHEN 0 THEN 'OK' ELSE 'KO' END AS ESITO, 
                CASE WHEN dbo.ARCHIVEDEST.XMODE IN ('R', 'K', 'H') THEN 'RX' ELSE 'TX' END AS [T/R], 
        
            ...
        ) t
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-10
          • 2014-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多