1

假设我在 SQL Server 2012 中有一个包含两列的表 UserActivity:

  • 活动日期时间
  • 用户身份

我想每天计算 30 天内有任何活动的不同用户的数量(我的每月活跃用户)。(所以我有一个 30 天的窗口,每次递增一天。如何使用 SQL Server 中的窗口函数有效地做到这一点?

输出将如下所示:

Date,NumberActiveUsersInPrevious30Days
01-01-2010,13567
01-02-2010,14780
01-03-2010,13490
01-04-2010,15231
01-05-2010,15321
01-06-2010,14513
...
4

2 回答 2

1

SQL Server doesn't support COUNT(DISTINCT ... ) OVER () or a numeric value (30 PRECEDING) in conjunction with RANGE

I wouldn't bother trying to coerce window functions into doing this. Because of the COUNT(DISTINCT UserID) requirement it is always going to have to re-examine the entire 30 day window for each date.

You can create a calendar table with a row for each date and use

SELECT C.Date,
       NumberActiveUsersInPrevious30Days
FROM   Calendar C
       CROSS APPLY (SELECT COUNT(DISTINCT UserID)
                   FROM   UserActivity
                   WHERE  ActivityDateTime >= DATEADD(DAY, -30, C.[Date])
                   AND ActivityDateTime < C.[Date]) CA(NumberActiveUsersInPrevious30Days)
WHERE  C.Date BETWEEN '2010-01-01' AND '2010-01-06' 
于 2013-01-25T11:48:18.017 回答
0

选项 1: For (while) 每天循环并为每个选择向后 30 天(显然很慢)。

选项 2:一个单独的表,每天有一行,并加入原始表(同样很慢)。

选项 3:递归 CTE 或存储过程(仍然没有做得更好)。

选项 4:结合游标的 For (while) 循环(高效,但需要一些高级 SQL 知识)。使用此解决方案,您将按顺序遍历每一天和每一行并跟踪平均值(您需要某种环绕数组来知道当一天超出范围时要减去什么值)。

选项 5:通用/脚本编程语言(C++/Java/PHP)中的选项 3(只需具备其中一种语言的基本知识即可轻松完成,高效)。

一些 相关的 问题

于 2013-01-25T08:23:16.380 回答