SQL 查询时间序列数据以查找用户 activity 的趋势计数
SQL query time series data to find trend counts for user activity
使用 Postgres 8.4。我有一个 table 的用户 activity,看起来有点像这样:
userid | timestamp | action
---------------------------------------------
0001 | 11/11/2015 9:00:02 | X
0001 | 11/11/2015 9:00:22 | Y
0002 | 11/11/2015 9:01:02 | Z
0002 | 11/11/2015 9:03:02 | W
0003 | 11/11/2015 9:04:02 | X
0004 | 11/11/2015 9:05:02 | Y
我需要做的是计算执行一系列操作的用户数量 X,然后是 Y
或 X 然后 Y 然后 Z 统计有多少用户进入下一个步骤.
所以我输入了一组有序的操作,我想计算有多少用户完成了这些操作(第一步:操作 1,第二步:操作 2,第三步)
我正在努力获得类似
的结果
step | action | count
=======================
1 | X | 100 <---- 100 users did X
2 | Y | 55 <-----55 did X and then Y (45 dropped away)
3 | Z | 12 <-----12 did X and then Y and then Z (43 more dropped)
如您所见,计数一直在减少:100 名用户做了 X,其中 55 名用户做了 Y,12 名用户做了 Z。
我怎样才能做到这一点?
我相信一定有更好的方法来使用其他 SQL 功能。
但一个简单的方法就是执行类似于我在下面粘贴的查询。
那会为您提供执行 X-Y-Z 的用户,X-Y 应该可以通过修改此查询轻松完成。
select count(distinct(userid)) from user_activity u1
where action = 'Z'
and exists
(select userid from user_activity u2
where u2.userid = u1.userid
and u2.date < u1.date
and u2.action = 'Y'
and exists (
select userid from user_activity u3
where u3.userid = u2.userid
and u3.date < u2.date
and u3.action = 'X'
)
)
这是一种相当蛮力的方法。使用 listagg()
创建序列,然后查找它们:
select p.pattern, count(t.actions)
from (select 'X' as pattern union all select 'XY' union all SELECT 'XYZ'
) p left join
(select userid, listagg(action, '') within group (order by timestamp) actions
from table t
group by userid
) t
on t.actions like concat('%', p.pattern, '%')
group by p.pattern;
最简单的解决方案可能是使用 LEFT JOIN
将 table 与自身连接起来:
WITH actions(action) AS(
VALUES ('X'),('Y'),('Z'))
SELECT d.action
,Count(DISTINCT a.userid)
FROM table1 as a
LEFT JOIN table1 AS b
ON a.userid = b.userid AND b.action = 'Y' AND a.timestamp < b.timestamp
LEFT JOIN table1 AS c
ON a.userid = c.userid AND c.action = 'Z' AND b.timestamp < c.timestamp
JOIN actions AS d
ON d.action IN (a.action, b.action, c.action)
WHERE a.action = 'X'
GROUP BY d.action
使用 Postgres 8.4。我有一个 table 的用户 activity,看起来有点像这样:
userid | timestamp | action
---------------------------------------------
0001 | 11/11/2015 9:00:02 | X
0001 | 11/11/2015 9:00:22 | Y
0002 | 11/11/2015 9:01:02 | Z
0002 | 11/11/2015 9:03:02 | W
0003 | 11/11/2015 9:04:02 | X
0004 | 11/11/2015 9:05:02 | Y
我需要做的是计算执行一系列操作的用户数量 X,然后是 Y 或 X 然后 Y 然后 Z 统计有多少用户进入下一个步骤.
所以我输入了一组有序的操作,我想计算有多少用户完成了这些操作(第一步:操作 1,第二步:操作 2,第三步)
我正在努力获得类似
的结果step | action | count
=======================
1 | X | 100 <---- 100 users did X
2 | Y | 55 <-----55 did X and then Y (45 dropped away)
3 | Z | 12 <-----12 did X and then Y and then Z (43 more dropped)
如您所见,计数一直在减少:100 名用户做了 X,其中 55 名用户做了 Y,12 名用户做了 Z。
我怎样才能做到这一点?
我相信一定有更好的方法来使用其他 SQL 功能。
但一个简单的方法就是执行类似于我在下面粘贴的查询。
那会为您提供执行 X-Y-Z 的用户,X-Y 应该可以通过修改此查询轻松完成。
select count(distinct(userid)) from user_activity u1
where action = 'Z'
and exists
(select userid from user_activity u2
where u2.userid = u1.userid
and u2.date < u1.date
and u2.action = 'Y'
and exists (
select userid from user_activity u3
where u3.userid = u2.userid
and u3.date < u2.date
and u3.action = 'X'
)
)
这是一种相当蛮力的方法。使用 listagg()
创建序列,然后查找它们:
select p.pattern, count(t.actions)
from (select 'X' as pattern union all select 'XY' union all SELECT 'XYZ'
) p left join
(select userid, listagg(action, '') within group (order by timestamp) actions
from table t
group by userid
) t
on t.actions like concat('%', p.pattern, '%')
group by p.pattern;
最简单的解决方案可能是使用 LEFT JOIN
将 table 与自身连接起来:
WITH actions(action) AS(
VALUES ('X'),('Y'),('Z'))
SELECT d.action
,Count(DISTINCT a.userid)
FROM table1 as a
LEFT JOIN table1 AS b
ON a.userid = b.userid AND b.action = 'Y' AND a.timestamp < b.timestamp
LEFT JOIN table1 AS c
ON a.userid = c.userid AND c.action = 'Z' AND b.timestamp < c.timestamp
JOIN actions AS d
ON d.action IN (a.action, b.action, c.action)
WHERE a.action = 'X'
GROUP BY d.action