2017-08-15 190 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.... 

注: