我有一张左桌子:
CREATE TABLE tab (
code int
, max date
, min date
);
还有一个带有用户活动的右表(每个用户每天一行):
CREATE TABLE activity (
date date
, "user" text
);
样本数据:
表tab
(带有我要计算的添加列):
Code Min Max (Expected output)
201 2019-1-8 2019-1-10 3
202 2019-1-8 2019-1-11 3
203 2019-1-11 2019-1-12 2
表activity
:
Date User
2019-1-8 ABCD001
2019-1-8 ABCD002
2019-1-9 ABCD001
2019-1-9 ABCD003
2019-1-10 ABCD001
2019-1-11 ABCD002
2019-1-12 ABCD003
我希望将tab
的列作为输出,并扩展该日期范围内的不同用户activity
的数量
所以我需要以某种方式加入min
和max
之间的日期范围。
审判1:
select code, min, max, count(b.distinct user)
from tab a
left join activity b on b.date between a.min and a.max
group by 1,2,3
审判2:
select code, min, max, count(b.distinct user)
from tab a
left join activity b on b.date <= a.min and b.date >=a.max and b.date = a.min
group by 1,2,3
我运行了上述代码的不同版本,但是运行可能要花一些时间,否则就会失败。
我建议使用LEFT JOIN LATERAL
:
SELECT a.code, a.min, a.max, b.ct
FROM tab a
LEFT JOIN LATERAL (
SELECT count(DISTINCT b."user") AS ct
FROM activity b
WHERE b.date BETWEEN a.min AND a.max
) b ON true;
如果范围不小,这样的查询可能会很昂贵。左侧的每一行都包含右侧的一系列行。对于大范围,DISTINCT
计数最昂贵。但这应该是最快的查询。
在activity(date, "user")
上用index支持。如果您仅从第二列开始扫描,则仅添加第二列。
user
是reserved word,顺便说一句。不要将其用作标识符。而且我也不会使用date
,min
或max
。基本数据类型的名称和用作标识符的功能可能会导致令人困惑的错误。
相关: