查询 SQL 中带状 DATEDIFF(DAY) 的有效方式(使用预计算)
Query efficient way of banding DATEDIFF(DAY) in SQL (with a pre-calculation)
我目前有两个日期字段,effective_date 和 invoice_date。我正在查找这两个日期中的最近日期,然后计算出该日期与今天(或报告为 运行 时)之间的天数。然后我使用它在 'Ageing' 列中创建一个标签,以将结果分组到年龄段中。我当前的代码是这样的:
SELECT TOP 500
'Ageing' = CASE WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) < 0 THEN 'Prebill'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 0 AND 29 THEN '<30 Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 30 AND 59 THEN '30+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 60 AND 89 THEN '60+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 90 AND 119 THEN '90+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 120 AND 179 THEN '120+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 180 AND 364 THEN '180+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) >= 365 THEN '365+ Days'
ELSE NULL
END
FROM [transaction] tbis
这种方法工作正常,但我目前只查看 150,000 条记录。很快这将是 运行 潜在的数百万条记录。
因此,我想看看是否可以改进它的编写方式。我已经使用另一个 SELECT 和 MAX() 方法查看了下面的内容:
DATEDIFF(DAY, (SELECT MAX(v)
FROM ( VALUES ( t.effective_date_key), ( t.invoice_date_key) ) AS value (v)
), GETDATE())
这在单独使用时效果很好 - 获取每条记录的旧天数。但是当嵌套到上面的 case 语句中时,它会产生以下错误:
消息 0,级别 11,状态 0,第 0 行
当前命令发生严重错误。结果,如果有的话,应该被丢弃。
消息 0,级别 20,状态 0,行 0
当前命令发生严重错误。结果,如果有的话,应该被丢弃。
任何关于如何以更有效的方式实现我的目标的想法都会很棒。或者,也许我现有的案例陈述是最好的方法?
试试这个,我想它会稍微快一点,更 reader 友好:
SELECT TOP 500
'Ageing' =
CASE WHEN x.datedif < 0 THEN 'Prebill'
WHEN x.datedif < 30 THEN '<30 Days'
WHEN x.datedif < 60 THEN '30+ Days'
WHEN x.datedif < 90 THEN '60+ Days'
WHEN x.datedif < 120 THEN '90+ Days'
WHEN x.datedif < 180 THEN '120+ Days'
WHEN x.datedif >= 180 THEN '180+ Days'
ELSE NULL
END
FROM [transaction] tbis
CROSS APPLY
(
SELECT
DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) datedif
) x
我目前有两个日期字段,effective_date 和 invoice_date。我正在查找这两个日期中的最近日期,然后计算出该日期与今天(或报告为 运行 时)之间的天数。然后我使用它在 'Ageing' 列中创建一个标签,以将结果分组到年龄段中。我当前的代码是这样的:
SELECT TOP 500
'Ageing' = CASE WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) < 0 THEN 'Prebill'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 0 AND 29 THEN '<30 Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 30 AND 59 THEN '30+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 60 AND 89 THEN '60+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 90 AND 119 THEN '90+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 120 AND 179 THEN '120+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) BETWEEN 180 AND 364 THEN '180+ Days'
WHEN DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) >= 365 THEN '365+ Days'
ELSE NULL
END
FROM [transaction] tbis
这种方法工作正常,但我目前只查看 150,000 条记录。很快这将是 运行 潜在的数百万条记录。
因此,我想看看是否可以改进它的编写方式。我已经使用另一个 SELECT 和 MAX() 方法查看了下面的内容:
DATEDIFF(DAY, (SELECT MAX(v)
FROM ( VALUES ( t.effective_date_key), ( t.invoice_date_key) ) AS value (v)
), GETDATE())
这在单独使用时效果很好 - 获取每条记录的旧天数。但是当嵌套到上面的 case 语句中时,它会产生以下错误:
消息 0,级别 11,状态 0,第 0 行 当前命令发生严重错误。结果,如果有的话,应该被丢弃。 消息 0,级别 20,状态 0,行 0 当前命令发生严重错误。结果,如果有的话,应该被丢弃。
任何关于如何以更有效的方式实现我的目标的想法都会很棒。或者,也许我现有的案例陈述是最好的方法?
试试这个,我想它会稍微快一点,更 reader 友好:
SELECT TOP 500
'Ageing' =
CASE WHEN x.datedif < 0 THEN 'Prebill'
WHEN x.datedif < 30 THEN '<30 Days'
WHEN x.datedif < 60 THEN '30+ Days'
WHEN x.datedif < 90 THEN '60+ Days'
WHEN x.datedif < 120 THEN '90+ Days'
WHEN x.datedif < 180 THEN '120+ Days'
WHEN x.datedif >= 180 THEN '180+ Days'
ELSE NULL
END
FROM [transaction] tbis
CROSS APPLY
(
SELECT
DATEDIFF(DD,
CASE WHEN tbis.invoice_date_key > tbis.effective_date_key
THEN tbis.invoice_date_key
ELSE tbis.effective_date_key
END, GETDATE()) datedif
) x