计算限制为 7 的用户的访问次数
Calculate the streaks of visit of users limited to 7
我正在尝试计算用户对应用程序的连续访问。我使用排名函数来确定每个用户维护的条纹。不过我的要求是条纹不能超过7条。
例如,如果用户连续 9 天访问该应用。他将有 2 次不同的连胜:一次是 7 次,一次是 2 次。
使用MaxCompute。它类似于 MySQL。
我有以下 table 名为 visitors_data:
user_id visit_date
murtaza 01-01-2021
john 01-01-2021
murtaza 02-01-2021
murtaza 03-01-2021
murtaza 04-01-2021
john 01-01-2021
murtaza 05-01-2021
murtaza 06-01-2021
john 02-01-2021
john 03-01-2021
murtaza 07-01-2021
murtaza 08-01-2021
murtaza 09-01-2021
john 20-01-2021
john 21-01-2021
输出应如下所示:
user_id streak
murtaza 7
murtaza 2
john 3
john 2
我能够通过以下查询获得条纹,但我无法将条纹限制为 7。
WITH groups AS (
SELECT user_id,
RANK() OVER (ORDER BY user_id, visit_date) AS RANK,
visit_date,
DATEADD(visit_date, -RANK() OVER (ORDER BY user_id, visit_date), 'dd') AS date_group
FROM visitors_data
ORDER BY user_id, visit_date)
SELECT
user_id,
COUNT(*) AS streak
FROM groups
GROUP BY
user_id,
date_group
HAVING COUNT(*)>1
ORDER BY COUNT(*);
你可以事后分手。例如,如果您从来没有超过 21 个:
SELECT user_id, LEAST(streak, 7)
FROM (SELECT user_id, COUNT(*) AS streak
FROM groups
GROUP BY user_id, date_group
HAVING COUNT(*) > 1
) gu JOIN
(SELECT 1 as n UNION ALL SELECT 2 as n UNION ALL SELECT 3 UNION ALL SELECT 4
) n
ON streak >= n * 7
ORDER BY LEAST(streak, 7);
如果最长连胜的数字范围不确定,您可以使用递归 CTE 做类似的事情>
混合使用 window 函数和聚合:
SELECT user_id, COALESCE(NULLIF(MAX(counter) % 7, 0), 7) streak
FROM (
SELECT *, COUNT(*) OVER (PARTITION BY user_id, grp ORDER BY visit_date) counter
FROM (
SELECT *, SUM(flag) OVER (PARTITION BY user_id ORDER BY visit_date) grp
FROM (
SELECT *, COALESCE(DATE_ADD(visit_date, INTERVAL -1 DAY) <>
LAG(visit_date) OVER (PARTITION BY user_id ORDER BY visit_date), 1) flag
FROM (SELECT DISTINCT * FROM visitors_data) t
) t
) t
) t
GROUP BY user_id, grp, FLOOR((counter - 1) / 7)
参见demo。
我的想法 运行 与 forpas 类似:
SELECT user_id, COUNT(*) streak
FROM
(
SELECT
user_id, streak,
FLOOR((ROW_NUMBER() OVER (PARTITION BY user_id, streak ORDER BY visit_date)-1)/7) substreak
FROM
(
SELECT
user_id, visit_date,
SUM(runtot) OVER (PARTITION BY user_id ORDER BY visit_date) streak
FROM (
SELECT
user_id, visit_date,
CASE WHEN DATE_ADD(visit_date, INTERVAL -1 DAY) = LAG(visit_date) OVER (PARTITION BY user_id ORDER BY visit_date) THEN 0 ELSE 1 END as runtot
FROM visitors_data
GROUP BY user_id, visit_date
) x
) y
) z
GROUP BY user_id, streak, substreak
解释其工作原理;计算 运行s 连续记录的常用技巧是使用 LAG 检查之前的记录,如果只有例如一天之差则填 0,否则填 1。这意味着连续 运行 的第一条记录为 1,其余均为 0,因此该列最终看起来像 1,0,0, 0,1,0... SUM OVER ORDER BY 以“运行ning total”方式对其求和。这实际上意味着它形成一个计数器,每次遇到 运行 的开始时都会向上计数,因此 运行 4 天后跟一个间隙然后 运行 3 天看起来像 1 ,1,1,1,2,2,2 等,形成一个“连续 ID 号”。
如果将其送入按连续 ID 号分区的行编号,它会建立一个递增计数器,每次连续 ID 更改时都会重新启动。如果我们从这个中减去 1 所以它 运行s 从 0 而不是 1 那么我们可以将它除以 7 以获得我们的 9 长连胜的“子连胜 ID”,即 0,0,0,0, 0,0,0,1,1(依此类推。25 连胜将有 7 个零、7 个一、7 个二和 4 个三)
剩下的就是按用户、连胜 ID、子连胜 ID 分组并计算结果
在最后一组和统计数据之前看起来是这样的:
这应该让我们了解它是如何工作的
我正在尝试计算用户对应用程序的连续访问。我使用排名函数来确定每个用户维护的条纹。不过我的要求是条纹不能超过7条。
例如,如果用户连续 9 天访问该应用。他将有 2 次不同的连胜:一次是 7 次,一次是 2 次。
使用MaxCompute。它类似于 MySQL。
我有以下 table 名为 visitors_data:
user_id visit_date
murtaza 01-01-2021
john 01-01-2021
murtaza 02-01-2021
murtaza 03-01-2021
murtaza 04-01-2021
john 01-01-2021
murtaza 05-01-2021
murtaza 06-01-2021
john 02-01-2021
john 03-01-2021
murtaza 07-01-2021
murtaza 08-01-2021
murtaza 09-01-2021
john 20-01-2021
john 21-01-2021
输出应如下所示:
user_id streak
murtaza 7
murtaza 2
john 3
john 2
我能够通过以下查询获得条纹,但我无法将条纹限制为 7。
WITH groups AS (
SELECT user_id,
RANK() OVER (ORDER BY user_id, visit_date) AS RANK,
visit_date,
DATEADD(visit_date, -RANK() OVER (ORDER BY user_id, visit_date), 'dd') AS date_group
FROM visitors_data
ORDER BY user_id, visit_date)
SELECT
user_id,
COUNT(*) AS streak
FROM groups
GROUP BY
user_id,
date_group
HAVING COUNT(*)>1
ORDER BY COUNT(*);
你可以事后分手。例如,如果您从来没有超过 21 个:
SELECT user_id, LEAST(streak, 7)
FROM (SELECT user_id, COUNT(*) AS streak
FROM groups
GROUP BY user_id, date_group
HAVING COUNT(*) > 1
) gu JOIN
(SELECT 1 as n UNION ALL SELECT 2 as n UNION ALL SELECT 3 UNION ALL SELECT 4
) n
ON streak >= n * 7
ORDER BY LEAST(streak, 7);
如果最长连胜的数字范围不确定,您可以使用递归 CTE 做类似的事情>
混合使用 window 函数和聚合:
SELECT user_id, COALESCE(NULLIF(MAX(counter) % 7, 0), 7) streak
FROM (
SELECT *, COUNT(*) OVER (PARTITION BY user_id, grp ORDER BY visit_date) counter
FROM (
SELECT *, SUM(flag) OVER (PARTITION BY user_id ORDER BY visit_date) grp
FROM (
SELECT *, COALESCE(DATE_ADD(visit_date, INTERVAL -1 DAY) <>
LAG(visit_date) OVER (PARTITION BY user_id ORDER BY visit_date), 1) flag
FROM (SELECT DISTINCT * FROM visitors_data) t
) t
) t
) t
GROUP BY user_id, grp, FLOOR((counter - 1) / 7)
参见demo。
我的想法 运行 与 forpas 类似:
SELECT user_id, COUNT(*) streak
FROM
(
SELECT
user_id, streak,
FLOOR((ROW_NUMBER() OVER (PARTITION BY user_id, streak ORDER BY visit_date)-1)/7) substreak
FROM
(
SELECT
user_id, visit_date,
SUM(runtot) OVER (PARTITION BY user_id ORDER BY visit_date) streak
FROM (
SELECT
user_id, visit_date,
CASE WHEN DATE_ADD(visit_date, INTERVAL -1 DAY) = LAG(visit_date) OVER (PARTITION BY user_id ORDER BY visit_date) THEN 0 ELSE 1 END as runtot
FROM visitors_data
GROUP BY user_id, visit_date
) x
) y
) z
GROUP BY user_id, streak, substreak
解释其工作原理;计算 运行s 连续记录的常用技巧是使用 LAG 检查之前的记录,如果只有例如一天之差则填 0,否则填 1。这意味着连续 运行 的第一条记录为 1,其余均为 0,因此该列最终看起来像 1,0,0, 0,1,0... SUM OVER ORDER BY 以“运行ning total”方式对其求和。这实际上意味着它形成一个计数器,每次遇到 运行 的开始时都会向上计数,因此 运行 4 天后跟一个间隙然后 运行 3 天看起来像 1 ,1,1,1,2,2,2 等,形成一个“连续 ID 号”。
如果将其送入按连续 ID 号分区的行编号,它会建立一个递增计数器,每次连续 ID 更改时都会重新启动。如果我们从这个中减去 1 所以它 运行s 从 0 而不是 1 那么我们可以将它除以 7 以获得我们的 9 长连胜的“子连胜 ID”,即 0,0,0,0, 0,0,0,1,1(依此类推。25 连胜将有 7 个零、7 个一、7 个二和 4 个三)
剩下的就是按用户、连胜 ID、子连胜 ID 分组并计算结果
在最后一组和统计数据之前看起来是这样的:
这应该让我们了解它是如何工作的