使用 T-SQL 的 n 天活跃用户的滚动计数 DISTINCT

Rolling COUNT DISTINCT of n-day active users using T-SQL

我正在使用 T-SQL 计算 7 天活跃用户。我使用了以下代码:

SELECT 
    *, 
    COUNT(DISTINCT [UserID]) OVER (
        PARTITION BY [HospitalID], [HospitalName], [Device]
        ORDER BY [Date]
        ROWS 7 PRECEDING
    ) AS [7-Day Active Users]
FROM UserActivity
ORDER BY [HospitalID], [HospitalName], [Device], [Date]

有人告诉我 Use of DISTINCT is not allowed with the OVER clauseUserActivity 是具有列 HospitalIDHospitalNameDevice(phone 或 tablet)、DateUserID(可以为 NULL)。为了让事情变得更简单,我填补了使 Date 连续的日期之间的空白,这样我就可以放心地使用 ROWS 7 PRECEDING。我在网上做了很多搜索,发现大多数解决方案要么使用其他类型的 SQL(这在我的情况下是不可能的),要么使用不支持移动 window 的 DENSE_RANK 函数.解决我的问题的正确且希望更简单、简洁的方法是什么?

示例数据:https://docs.google.com/spreadsheets/d/19vrBK8ixpiPJycRjb1ekiKnEUYk5AaUH/edit?usp=sharing&ouid=110206477774349430845&rtpof=true&sd=true

很抱歉看到 COUNT DISTINCT 在那种类型的 SQL 中不受支持...我以前不知道。尤其是在您费尽心力解决日期之间的差距之后!

我使用 Rasgo 生成了 SQL -- 所以这不会直接在你的版本中工作(用 Snowflake 测试过),但我认为只要你修复它就会工作DATEADD 函数。每个 RDBMS 似乎 DATEADD 都不同,似乎。

这里的一般概念是使用 WHERE 子句中的 range join 条件将数据连接到自身。

幸运的是,这应该对您有用,而无需先修复日期之间的差距。

WITH BASIC_OFFSET_7DAY AS (
  SELECT 
    A.HOSPITALNAME, 
    A.HOSPITALID, 
    A.DEVICE, 
    A.DATE, 
    COUNT(DISTINCT B.USERID) as COUNT_DISTINCT_USERID_PAST7DAY, 
    COUNT(1) AS AGG_ROW_COUNT 
  FROM 
    UserActivity A 
    INNER JOIN UserActivity B ON A.HOSPITALNAME = B.HOSPITALNAME 
    AND A.HOSPITALID = B.HOSPITALID 
    AND A.DEVICE = B.DEVICE 
  WHERE 
    B.DATE >= DATEADD(day, -7, A.DATE) 
    AND B.DATE <= A.DATE 
  GROUP BY 
    A.HOSPITALNAME, 
    A.HOSPITALID, 
    A.DEVICE, 
    A.DATE
) 
SELECT 
  src.*, 
  BASIC_OFFSET_7DAY.COUNT_DISTINCT_USERID_PAST7DAY 
FROM 
  UserActivity src 
  LEFT OUTER JOIN BASIC_OFFSET_7DAY ON BASIC_OFFSET_7DAY.DATE = src.DATE 
  AND BASIC_OFFSET_7DAY.HOSPITALNAME = src.HOSPITALNAME 
  AND BASIC_OFFSET_7DAY.HOSPITALID = src.HOSPITALID 
  AND BASIC_OFFSET_7DAY.DEVICE = src.DEVICE

让我知道结果如何,如果不起作用,我会帮助您。

编辑:对于那些尝试这样做并卡住的人来说,一个常见的错误(我自己在手动执行此操作时犯的错误)是要特别注意 COUNT(DISTINCT(B.col )) 而不是 A.col。当我使用 Rasgo 生成 SQL 来检查自己时,我发现了我的错误。希望这篇笔记对以后犯同样错误的人有所帮助!