【发布时间】:2021-01-15 07:07:42
【问题描述】:
[感谢 @Gordon Linoff 和 @shawnt00 的 cmets 编辑和修复查询和问题]
我最近继承了一个 SQL 查询,该查询从日志数据库中计算 30 天时间窗口中的某些事件的数量。它使用 CTE(公用表表达式)生成从 '2019-01-01' 到现在的 30 天范围。然后它以 30/60/90 天为间隔计算病例数。我不确定这是最好的方法。我所知道的是它需要很长时间才能运行,而且我不能 100% 理解它是如何工作的。所以我试图以一种有效的方式重建它(也许现在是最有效的方式,我不知道)。
我有几个问题:
- 我注意到的一件事是,查询不使用 DATEDIFF,而是简单地从日期中减去天数。这是一个好的做法吗?
- 有没有更好的方法来进行时间比较?
- 有没有更好的方法来完成整个事情?底线是:我需要按 30、60 和 90 天时间段内的发生次数汇总数据。
注意:LogDate 原始格式类似于 2019-04-01 18:30:12.000。
DECLARE @dt1 Datetime='2019-01-01'
DECLARE @dt2 Datetime=getDate();
WITH ctedaterange
AS (SELECT [Dates]=@dt1
UNION ALL
SELECT [dates] + 30
FROM ctedaterange
WHERE [dates] + 30<= @dt2)
SELECT
[dates],
lt.Activity, COUNT(*) as Total,
SUM(CASE WHEN lt.LogDate <= dates and lt.LogDate > dates - 90 THEN 1 ELSE 0 END) AS Activity90days,
SUM(CASE WHEN lt.LogDate <= dates and lt.LogDate > dates - 60 THEN 1 ELSE 0 END) AS Activity60days,
SUM(CASE WHEN lt.LogDate <= dates and lt.LogDate > dates - 30 THEN 1 ELSE 0 END) AS Activity30days
FROM ctedaterange AS cte
JOIN (SELECT Activity, CONVERT(DATE, LogDate) as LogDate FROM LogTable) AS lt
ON cte.[dates] = lt.LogDate
group by [dates], lt.Activity
OPTION (maxrecursion 0)
样本数据集(LogTable):
LogDate, Activity
2020-02-25 01:10:10.000, Activity01
2020-04-14 01:12:10.000, Activity02
2020-08-18 02:03:53.000, Activity02
2019-10-29 12:25:55.000, Activity01
2019-12-24 18:11:11.000, Activity03
2019-04-02 03:33:09.000, Activity01
预期输出(输出不反映上面显示的数据,因为我需要样本集中的行太多才能在这篇文章中显示)
正如我上面所说,底线是:我需要按 30、60 和 90 天时间段内的出现次数汇总数据。
Activity, Activity90days, Activity60days, Activity30days
Activity01, 3, 0, 1
Activity02, 1, 10, 2
Activity03, 5, 1, 3
感谢您的任何建议。
【问题讨论】:
-
(1) 标记您正在使用的数据库。 (2) 提供样本数据和期望的结果。 (3) 您的问题涉及一个时间范围,但问题包含其他时间范围。
-
这是创建所有日期的列表,然后计算每个日期的日志事件数。它处理那些没有记录事件的日期。两个表之间显然缺少连接,但这可能解释了为什么它很慢(我也怀疑这些数字是否正确。)
-
另外,您按
lt.Activity分组,但返回lt.Event未聚合。这应该会导致错误。 -
对不起 Gordon 和 Shawnt,我粘贴了不同的查询。我确定了时间表。我将添加一些示例数据。
-
嗨@shawnt00,缺少的连接是什么?
标签: sql sql-server aggregate datediff sliding-window