Postgres SQL:包含日期范围内所有日期的唯一行的新表

时间:2017-11-08 21:12:16

标签: sql postgresql date

寻找关于从何处开始查询的一些指导,这些问题让我头疼。

我有一张表格显示试用开始时间&每个帐户的结束日期,如下所示:

account_id  trial_start  trial_end
==========  ===========  =========
123         1/2/2017     1/9/17
234         1/8/2017     1/21/17
456         1/15/2017    5/10/17

试用开始日期和结束日期各不相同,我想要一个结果表格,向我显示一年中每周的每个帐户ID。通过这种方式,我可以说我在一年中的每个星期都进行了多少次活动试验,并且可以查看在试用期间有多少这些帐户实际登录。也许是这样的事情:

week         account_id
===========  =========
1/1/2017     123
1/8/2017     123
1/8/2017     234
1/15/2017    234
1/15/2017    456
1/22/2017    456
...
5/7/2017     456

我有一个参考表,每年的每个星期都有一行,我觉得我需要以某种方式将我的帐户ID加入到该表中的每一行,但我无法弄清楚每周如何映射在每个星期的行的开始和结束日期之间,以便我捕获之间的日期:/

1 个答案:

答案 0 :(得分:0)

形成笛卡尔帐户和周数的产品,然后将周盯着日期放在跟踪日期中(这将每周提取一次)。

SQL Fiddle

PostgreSQL 9.6架构设置

CREATE TABLE TrialDates
    (account_id int, trial_start timestamp, trial_end timestamp)
;

INSERT INTO TrialDates
    ("account_id", "trial_start", "trial_end")
VALUES
    (678, '2017-01-04 00:00:00', '2017-01-05 00:00:00'),
    (123, '2017-01-02 00:00:00', '2017-01-09 00:00:00'),
    (234, '2017-01-08 00:00:00', '2017-01-21 00:00:00'),
    (456, '2017-01-15 00:00:00', '2017-05-10 00:00:00')
;


CREATE TABLE Weeks
    ("week_start" timestamp)
;

INSERT INTO Weeks
    ("week_start")
VALUES
    ('2017-01-16 00:00:00'),
    ('2017-01-09 00:00:00'),
    ('2017-01-02 00:00:00')
;

查询1 :( 已编辑

select  w.week_start, td.account_id
from (select distinct account_id from TrialDates) a
cross join Weeks w
inner join TrialDates td on a.account_id = td.account_id
and (
      w.week_start >= td.trial_start and w.week_start < trial_end
    OR
      td.trial_start >= w.week_start and td.trial_start < w.week_start + interval '7 days'
    )   
order by  w.week_start, td.account_id

<强> Results

|           week_start | account_id |
|----------------------|------------|
| 2017-01-02T00:00:00Z |        123 |
| 2017-01-02T00:00:00Z |        234 |
| 2017-01-02T00:00:00Z |        678 |
| 2017-01-09T00:00:00Z |        234 |
| 2017-01-09T00:00:00Z |        456 |
| 2017-01-16T00:00:00Z |        234 |
| 2017-01-16T00:00:00Z |        456 |

加入

对于可能没有现有周表的读者,使用PostgreSQL非常出色的generate_series功能可以获得相同的结果。因此,动态生成周数的交叉连接,系列的下边界和上边界日期也是动态确定的。

select  w.week_start, td.account_id
from (select distinct account_id from TrialDates) a
cross join (
      select
          date_trunc('week', dates.d) as week_start
      from generate_series(
              (select date_trunc('week',min(trial_start)) from TrialDates)
             , 
              (select date_trunc('week',max(trial_start) + interval '6 days') from TrialDates)
             , '1 day'
             ) as dates(d)
      group by 1
      ) w
inner join TrialDates td on a.account_id = td.account_id
and (
      w.week_start >= td.trial_start and w.week_start < trial_end
    OR
      td.trial_start >= w.week_start and td.trial_start < w.week_start + interval '7 days'
    )       
order by  w.week_start, td.account_id
;