【问题标题】:Using CASE logic after DATEDIFF在 DATEDIFF 之后使用 CASE 逻辑
【发布时间】:2018-05-18 18:06:10
【问题描述】:

我正在成功地使用 DATEDIFF 逻辑来计算年龄。然后我需要能够获取 Age 并将其用作 CASE 逻辑中的列。当我尝试这样做时,SMSS 会在红色下划线 Age 并指示它是无效列。我该如何解决这个问题?

USE DataWarehouse
SELECT DISTINCT
M.[Account Name Birth Date] as 'Birth Date',
M.[Mailing Address State] as 'State',
E.[ANSVIES2] as 'Income',
E.[FICO] as 'FICO Score',

DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 as [Age],

CASE WHEN [Age] >= 18 AND [Age] <= 34 AND E.[ANSVIES2] >= 50 THEN 'Credit 
Driven'
WHEN [Age] < 45 AND E.[ANSVIES2] < 50 THEN 'Fee Driven'
WHEN [Age] >= 35 AND [Age] <= 54 AND E.[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 
125 THEN 'Middle Market'
WHEN [Age] >= 45 AND E.[ANSVIES2] < 50 THEN 'Low Income Depositor'
WHEN [Age] >= 55 AND E.[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 125 THEN 'Middle 
Income Depositor'
WHEN [Age] >= 35 AND E.[ANSVIES2] >= 125 THEN 'Upscale'
ELSE 'Unclassified' END as 'Consumer Segment'

【问题讨论】:

  • 将其转储到临时表中,然后从那里与您的案例块一起选择
  • 我从未使用过临时表。我会研究一下。感谢您的回复。
  • 它非常简单。你只需要做select whatever fields into #temp from table 然后select case when... from #temp

标签: sql sql-server tsql case datediff


【解决方案1】:

或使用子选择(根据您的数据库大小和索引,临时表或临时表可能会更好,但这应该可行):

   Select CASE WHEN [Age] >= 18 AND [Age] <= 34 AND E.[ANSVIES2] >= 50 THEN 'Credit 
Driven'
WHEN [Age] < 45 AND E.[ANSVIES2] < 50 THEN 'Fee Driven'
WHEN [Age] >= 35 AND [Age] <= 54 AND E.[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 
125 THEN 'Middle Market'
WHEN [Age] >= 45 AND E.[ANSVIES2] < 50 THEN 'Low Income Depositor'
WHEN [Age] >= 55 AND E.[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 125 THEN 'Middle 
Income Depositor'
WHEN [Age] >= 35 AND E.[ANSVIES2] >= 125 THEN 'Upscale'
ELSE 'Unclassified' END as 'Consumer Segment'
, OtherColumnsHere
FROM (
     SELECT DISTINCT
     M.[Account Name Birth Date] as 'Birth Date',
     M.[Mailing Address State] as 'State',
     E.[ANSVIES2] as 'Income',
     E.[FICO] as 'FICO Score',    
     DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 as [Age],
     FROM RestOfYourSelectStatementHere
) SubSelect

【讨论】:

  • 我无法成功地将其应用到我的代码中,但这个解决方案有效 -
【解决方案2】:

SSMS 突出显示您的语法的原因是logical-processing order of SQL

简单地说,选择阶段中使用的别名“Age”,不能在同一阶段引用——它可以在后续阶段引用——(例如下一阶段 - ORDER BY)。

因此,一个解决方法是创建一个 CTE嵌套表

查询的逻辑步骤顺序:

  1. FROM/JOIN/APPLY/PIVOT/UNPIVOT
  2. 在哪里
  3. 分组依据
  4. 选择列表/DISTINCT
  5. 订购人
  6. TOP/OFFSET-FETCH

【讨论】:

  • 很好的解释,我只是给了他一个可能的解决方案你解释了它。
【解决方案3】:

你不需要使用subquery,你可以直接使用value构造来表达:

 SELECT  . . . ,
        (CASE WHEN tt.Age >= 18 AND tt.Age <= 34 AND t.[ANSVIES2] >= 50 
              THEN 'Credit Driven'
              WHEN [Age] < 45 AND E.[ANSVIES2] < 50 THEN 'Fee Driven'
              WHEN [Age] >= 35 AND [Age] <= 54 AND 
                   E.[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 125 
              THEN 'Middle Market'
              WHEN [Age] >= 45 AND E.[ANSVIES2] < 50 
              THEN 'Low Income Depositor'
              WHEN [Age] >= 55 AND E.[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 125 
              THEN 'Middle Income Depositor'
              WHEN [Age] >= 35 AND E.[ANSVIES2] >= 125 THEN 'Upscale'
              ELSE 'Unclassified'
         END) AS [Consumer Segment]
FROM table t 
CROSS APPLY (VALUES 
                (DATEDIFF(DD, t.[Account Name Birth Date],GETDATE())/365)
            ) tt(Age); 

【讨论】:

  • 我觉得有趣的是您仍然继续使用 子查询 :)
【解决方案4】:

上面发布的代码由于某种原因不起作用。不过,我能够成功实施此解决方案 -

USE DataWarehouse
SELECT DISTINCT
M.[Symitar Account Id] as 'Symitar ID',
M.[Account Name Birth Date] as 'Birth Date',
M.[Account Name Death Date] as 'Death Date',
M.[Mailing Address State] as 'State',
E.[ANSVIES2] as 'Income',
E.[FICO] as 'FICO Score',
M.[Loan Type] as 'Loan Description',
M.[Loan Type Code] as 'Loan Type',
M.[Share Type] as 'Share Description',
M.[Share Type Code] as 'Share Type',

DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 as [Age],

CASE WHEN DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 >= 18 AND 
DATEDIFF(DD,M.[Account Name Birth Date],
GETDATE())/365 <= 34 AND E.[ANSVIES2] >= 50 THEN 'Credit Driven'
WHEN DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 < 45 AND E. 
[ANSVIES2] < 50 THEN 'Fee Driven'
WHEN DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 >= 35 AND 
DATEDIFF(DD,M.[Account Name Birth Date],
GETDATE())/365 <= 54 AND E.[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 125 THEN 
'Middle Market'
WHEN DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 >= 45 AND E. 
[ANSVIES2] < 50 THEN 'Low Income Depositor'
WHEN DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 >= 55 AND E. 
[ANSVIES2] >= 50 AND E.[ANSVIES2] <= 125 
THEN 'Middle Income Depositor'
WHEN DATEDIFF(DD,M.[Account Name Birth Date],GETDATE())/365 >= 35 AND E. 
[ANSVIES2] >= 125 THEN 'Upscale'
ELSE 'Unclassified' END as 'Consumer Segment'

FROM Accounts.ExperianData E
INNER JOIN Accounts.MemberCube M
ON E.[Symitar Account Id] = M.[Symitar Account Id]
WHERE M.[Account Name Type] = 'Primary' AND /* Primary acct holders */
M.[Account Status] = 'Open' AND 
M.[Account Type] IN ('General Membership', 'Indirect Account', 'Employee Acc 
ount') AND 
/* Remove businesses and internal accounts */
M.[Account Name Birth Date] <= '05/18/1997' /* Older than 21 */ AND
M.[Mailing Address State] IN('UT', 'ID', 'AZ', 'NV', 'NM') 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 2019-05-08
    相关资源
    最近更新 更多