2017-08-15 192 views
2

我有很長的SELECT查詢,但我在這裏粘貼了相關部分。在另一個Case語句中使用Case語句的結果

我需要使用我的CASE語句的結果在另一個CASE語句中使用。我在SQL Server中這樣做。

非常感謝您的幫助。

SELECT 
    CompanyContact.Name AS CompanyName, 
    CASE 
     WHEN SUBSTRING(HeadLease.TenantBreakNotice, LEN(HeadLease.TenantBreakNotice), 1) = 'M' 
      THEN CONVERT(VARCHAR(10), DATEADD(DD, -365/(12/SUBSTRING(HeadLease.TenantBreakNotice, 1, LEN(HeadLease.TenantBreakNotice) - 1)), HeadLease.TenantBreakDate), 103) 
     WHEN SUBSTRING(HeadLease.TenantBreakNotice, LEN(HeadLease.TenantBreakNotice), 1) = 'Y' 
      THEN CONVERT(VARCHAR(10), DATEADD(DD, -365 * (SUBSTRING(HeadLease.TenantBreakNotice, 1, LEN(HeadLease.TenantBreakNotice) - 1)), HeadLease.TenantBreakDate), 103) 
     ELSE HeadLease.TenantBreakNotice 
    END AS [TenantBreakNotice], <-- I need this to be used in the case statement below. 
    CASE 
     WHEN [TenantBreakNotice] < CONVERT(varchar(10), getdate(), 103) 
      THEN 'Expiry' 
     WHEN [TenantBreakNotice] IS NULL 
      THEN 'Expiry' 
     ELSE 'Break' 
    END AS [LeaseEventType] 
FROM 
    HeadLease 
+0

那是不可能的。如果將其放入子查詢中,則只能訪問計算列。 –

+0

不可能通過某種方式將派生字段(從第一個case語句)分配給可以在第二個Case語句中使用的變量來避免子查詢? – Learner

+0

另請注意,T-SQL中的CASE是**表達式**(不是*語句*) - 表達式(如'a + b')返回單個原子值 –

回答

2

使用CTE(公用表表達式)。在CTE中,您可以參考前一個CTE的列,以便您可以按照您的意願拆分CASE邏輯。

實施例:

WITH 
    CTE_1 AS 
    (
     SELECT 
      * 
      ,CASE 
       WHEN SUBSTRING(HeadLease.TenantBreakNotice,LEN(HeadLease.TenantBreakNotice),1) = 'M' 
        THEN CONVERT(VARCHAR(10), DATEADD(DD,-365/(12/SUBSTRING(HeadLease.TenantBreakNotice,1,LEN(HeadLease.TenantBreakNotice)-1)),HeadLease.TenantBreakDate), 103) 
       WHEN SUBSTRING(HeadLease.TenantBreakNotice,LEN(HeadLease.TenantBreakNotice),1) = 'Y' 
        THEN CONVERT(VARCHAR(10), DATEADD(DD,-365*(SUBSTRING(HeadLease.TenantBreakNotice,1,LEN(HeadLease.TenantBreakNotice)-1)),HeadLease.TenantBreakDate), 103) 
      ELSE 
       HeadLease.TenantBreakNotice 
      END AS [TenantBreakNotice] 
     ... 
    ), 

    CTE_2 AS 
    (
     SELECT 
      *  
      ,CASE 
       WHEN [TenantBreakNotice] < CONVERT(varchar(10),getdate(),103) THEN 'Expiry' 
       WHEN [TenantBreakNotice] IS NULL THEN 'Expiry' 
       ELSE 'Break' 
      END AS [LeaseEventType] 
     FROM 
      CTE_1 
    ) 

SELECT * FROM CTE_2 
1

在其被定義相同select不能使用列別名。通常的解決方案是重複邏輯(難以維護),使用子查詢或CTE。 SQL Server提供了另一種優雅的解決方案:

SELECT hl.Name AS CompanyName, v.TenantBreakNotice, 
     (CASE WHEN v.TenantBreakNotice < CONVERT(varchar(10), getdate(), 103) THEN 'Expiry' 
      WHEN TenantBreakNotice IS NULL THEN 'Expiry' 
      ELSE 'Break' 
     END) AS [LeaseEventType] 

FROM HeadLease hl OUTER APPLY 
    (VALUES (CASE WHEN SUBSTRING(hl.TenantBreakNotice, LEN(hl.TenantBreakNotice), 1) = 'M' 
        THEN CONVERT(VARCHAR(10), DATEADD(DAY, -365/(12/SUBSTRING(hl.TenantBreakNotice, 1, LEN(hl.TenantBreakNotice) -1)), hl.TenantBreakDate), 103) 
        WHEN SUBSTRING(hl.TenantBreakNotice, LEN(hl.TenantBreakNotice), 1) = 'Y' 
        THEN CONVERT(VARCHAR(10), DATEADD(DAY, -365*(SUBSTRING(hl.TenantBreakNotice,1, LEN(hl.TenantBreakNotice)-1)), hl.TenantBreakDate), 103) 
        ELSE hl.TenantBreakNotice 
       END) v(TenantBreakNotice); 

當然,邏輯是不正確的,因爲你是比較日期爲字符串。但是,這是你需要弄清楚自己的事情。日期操作不要將日期轉換爲字符串。而且,您應該輸出結果爲YYYY-MM-DD,這樣格式纔是明確的。

1

由於@Juergen指出的那樣,你不能做你想要什麼,但你可以計算在子查詢第一CASE表達,然後用它外包裹查詢:

WITH cte AS (
    SELECT 
     Name AS CompanyName, 
     CASE WHEN SUBSTRING(HeadLease.TenantBreakNotice,LEN(HeadLease.TenantBreakNotice), 1) = 'M' 
      THEN CONVERT(VARCHAR(10), DATEADD(DD,-365/(12/SUBSTRING(HeadLease.TenantBreakNotice,1,LEN(HeadLease.TenantBreakNotice)-1)),HeadLease.TenantBreakDate), 103) 
      WHEN SUBSTRING(HeadLease.TenantBreakNotice,LEN(HeadLease.TenantBreakNotice),1) = 'Y' 
      THEN CONVERT(VARCHAR(10), DATEADD(DD,-365*(SUBSTRING(HeadLease.TenantBreakNotice,1,LEN(HeadLease.TenantBreakNotice)-1)),HeadLease.TenantBreakDate), 103) 
      ELSE HeadLease.TenantBreakNotice 
     END AS [TenantBreakNotice] 
    FROM HeadLease 
) 

SELECT 
    Name, 
    TenantBreakNotice, 
    CASE WHEN TenantBreakNotice < CONVERT(varchar(10), getdate(), 103) 
     THEN 'Expiry' 
     WHEN TenantBreakNotice IS NULL THEN 'Expiry' 
     ELSE 'Break' 
    END AS [LeaseEventType] 
FROM cte; 
1

你可以移動第一case表達插入from通過使用派生表/子查詢像這樣:

select 
    cc.Name as CompanyName 
    , convert(varchar(10),hl.[TenantBreakNotice],103) as TenantBreakNotice 
    , case 
     when hl.[TenantBreakNotice] < getdate() then 'Expiry' 
     when hl.[TenantBreakNotice] is null then 'Expiry' 
     else 'Break' 
     end as [LeaseEventType] 
from (
    select *, 
     case 
      when substring(HeadLease.TenantBreakNotice,len(HeadLease.TenantBreakNotice),1) = 'M' 
       then dateadd(day,-365/(12/substring(HeadLease.TenantBreakNotice,1,len(HeadLease.TenantBreakNotice)-1)),HeadLease.TenantBreakDate) 
      when substring(HeadLease.TenantBreakNotice,len(HeadLease.TenantBreakNotice),1) = 'Y' 
       then dateadd(day,-365*(substring(HeadLease.TenantBreakNotice,1,len(HeadLease.TenantBreakNotice)-1)),HeadLease.TenantBreakDate) 
      else HeadLease.TenantBreakNotice 
     end as [TenantBreakNotice] 
    from HeadLease 
    ) as hl 
    inner join CompanyContact cc 
    on cc.... 

注: