sql - 简化 case 表达式中的 SQL case 语句
问题描述
我将如何在 T-SQL 中简化这个 case 语句?它提供了所需的结果,但非常笨重且难以阅读。我必须使用内部 case 语句将儒略日期(又名 6 位数字)转换为常规日期格式。
基本上我正在做一个日期差异(getdate(),案例陈述)。Getdate() 只返回现在的时间(即 2/27/2020),case 语句将儒略日期(即 123456)转换为正常日期(即 2020 年 1 月 1 日)。
如果查询是在 2 月 27 日今天运行的,这是预期的输出。
Select CASE
WHEN Datediff(day, Getdate(), CASE
WHEN a.wadpl = 0
THEN NULL
ELSE Dateadd(d, Substring(Cast(wadpl AS VARCHAR(6)), 4, 3) - 1, CONVERT(DATETIME, CASE
WHEN LEFT(Cast(wadpl AS VARCHAR(6)), 1) = '1'
THEN '20'
ELSE '21'
END + Substring(Cast(wadpl AS VARCHAR(6)), 2, 2) + '-01-01'))
END) < 0
THEN 'Overdue Now'
WHEN Datediff(day, Getdate(), CASE
WHEN a.wadpl = 0
THEN NULL
ELSE Dateadd(d, Substring(Cast(wadpl AS VARCHAR(6)), 4, 3) - 1, CONVERT(DATETIME, CASE
WHEN LEFT(Cast(wadpl AS VARCHAR(6)), 1) = '1'
THEN '20'
ELSE '21'
END + Substring(Cast(wadpl AS VARCHAR(6)), 2, 2) + '-01-01'))
END) <= 30
THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM Table_X
解决方案
这里很容易理解,假设 a.wadpl 是一个整数:
SELECT CASE
WHEN DATEDIFF(DAY, GETDATE(), DATEADD(DAY, a.wadpl % 1000, DATEADD(YEAR,a.wadpl / 1000,'1899-12-31'))) <0 THEN 'Overdue now'
WHEN DATEDIFF(DAY, GETDATE(), DATEADD(DAY, a.wadpl % 1000, DATEADD(YEAR,a.wadpl / 1000,'1899-12-31'))) <= 30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM Table_X
或者您可以通过使用子查询来简化(或者您可以使用 WITH):
SELECT CASE
WHEN Age <0 THEN 'Overdue now'
WHEN Age <= 30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM (
SELECT DATEDIFF(DAY,GETDATE(),
DATEADD(DAY,wadpl%1000,DATEADD(YEAR,wadpl/1000,'1899-12-31'))) Age, *
FROM Table_X) a
这当然会导致您对每一行进行此算术运算,并且您不能轻易使用任何索引。如果您询问聚合,那么我建议您做相反的事情,并预先计算日期并在您的查询中使用这些日期。您可能还需要考虑在 table_x 上放置一个持久计算列:
ALTER TABLE TABLE_X
ADD wadpl_dt AS
(DATEADD(DAY,wadpl%1000,DATEADD(YEAR,wadpl/1000,'1899-12-31'))) PERSISTED;
现在,您可以在需要日期时间的任何时候参考 table_x.wadpl_dt,您的查询将变为:
SELECT CASE
WHEN Age <0 THEN 'Overdue now'
WHEN Age <= 30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM (
SELECT DATEDIFF(DAY,GETDATE(), wadpl_dt) Age, *
FROM Table_X) a
这是将日期转换为儒略日期的简单方法:
SELECT (DATEPART(YEAR,GETDATE())-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE())
这就是你可以使用它的方式:
DECLARE @overdue int;
DECLARE @next30 int;
SET @overdue = (SELECT (DATEPART(YEAR,GETDATE())-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE()));
SET @next30 = (SELECT (DATEPART(YEAR,GETDATE()+30)-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE()+30));
SELECT CASE
WHEN wadpl < @overdue THEN 'Overdue now'
WHEN wadpl <= @next30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM Table_X
推荐阅读
- python - 如何使用 GeoPandas 执行空间查询?
- swift - AVAudioPlayer 没有播放任何东西
- mongodb-atlas - MongoDB Stitch 的最大并行触发器执行限制
- c# - 函数,删除所有代码注释
- reactjs - 与 express 后端反应
- node.js - 绕过服务器端 GET 请求的护照身份验证
- stm32f4discovery - 学习 Stm32f407 定时器基础知识。如何使用定时器计数寄存器来设置 LED?
- generics - 在 Kotlin 中的 when 子句中组合多个 is
- c++ - Eigen3:如何在性能关键操作中访问矩阵系数?
- ansible - Ansible:如何以没有外壳的用户身份运行命令