在2个日期之间加入并计算不同的值

问题描述 投票:1回答:1

我有一张左桌子:

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的数量

所以我需要以某种方式加入minmax之间的日期范围。

审判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

我运行了上述代码的不同版本,但是运行可能要花一些时间,否则就会失败。

sql postgresql join distinct date-range
1个回答
0
投票

我建议使用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支持。如果您仅从第二列开始扫描,则仅添加第二列。

userreserved word,顺便说一句。不要将其用作标识符。而且我也不会使用dateminmax。基本数据类型的名称和用作标识符的功能可能会导致令人困惑的错误。

相关:

© www.soinside.com 2019 - 2024. All rights reserved.