我正在运行Postgres 9.6。我有一个用户表:
id | integer | | not null | nextval('user_id_seq'::regclass)
name | character varying | | not null |
t_registered | timestamp without time zone | | not null |
我有一个action
表:
actioned_by | integer | | |
category | character varying | | not null |
t_actioned | timestamp without time zone | | not null |
我想要一种用整数字段num_days
注释每个用户的方法,该字段指示在用户注册后的30天内有多少不同的24小时行动。
我知道如何获取每个用户活跃的不同日历天的总数:
SELECT d.actioned_by, COUNT(*) AS cnt FROM
(SELECT date_trunc('day', t_actioned) AS day, actioned_by
FROM history
GROUP BY day, actioned_by) d
GROUP BY actioned_by
ORDER BY cnt DESC;
但是我在如何针对每个用户的30天时间窗口中获取此限制。
我怀疑这是高级SQL!
出于分析目的,我偶尔会运行它,因此它的运行速度是否慢并不重要。
答案 0 :(得分:0)
SELECT actioned_by, COUNT(*)
FROM (
SELECT actioned_by, date_trunc('day', t_actioned)
FROM history
JOIN user ON id = actioned_by
WHERE t_actioned BETWEEN t_registered AND t_registered + interval '30 days'
GROUP BY actioned_by, date_trunc('day', t_actioned)
) sub
GROUP BY actioned_by
所以首先,您说您想获得一个不同天的计数,因此您必须对date_trunc分组,否则您将在同一天(如果存在)对多个事件进行计数。
此查询的作用是,加入user
以获取每个用户的注册时间戳,确保t_actioned
在注册后30天内,然后按用户和唯一日期分组,最后每位用户计数。
如果要包括不执行任何操作的用户,则可以对其进行一些更改:从用户表中选择,并保留联接历史记录:
SELECT id, COUNT(*)
FROM (
SELECT id, date_trunc('day', t_actioned)
FROM user
LEFT JOIN history
ON id = actioned_by
AND t_actioned BETWEEN t_registered AND t_registered + interval '30 days'
GROUP BY id, date_trunc('day', t_actioned)
) sub
GROUP BY id
答案 1 :(得分:0)
您可以将COUNT
与FILTER
表达式一起使用:
SELECT
u.id,
u."name",
COUNT(*) FILTER (WHERE h.t_actioned BETWEEN u.t_registered AND u.t_registered + INTERVAL'30 days')
FROM
history h
JOIN "user" u ON u.id = h.actioned_by
GROUP BY
u.id,
u."name"
更多信息here。