Postgres - 生成系列
Postgres - Generate Series
我有一个 table (tb1),其中包含一个包含创建日期(A 列)和修改日期(B 列)的列。
我想要一个聚合度量值,显示在给定时间间隔内创建了多少记录,在同一时间间隔内修改了多少记录。
到目前为止,我已经尝试了以下代码:
Select count(distinct tb.id),dd
from generate_series ('2015-01-01'::timestamp,'2019-11-01'::timestamp,'1 month'::interval)dd
left join tb on tb.columnA<=dd::date
group by dd
我收到的输出很好,因为我得到了以下 table
dd/count
2015-01-01/ 2
2015-02-01/ 6
2015-03-01/ 10
2015-04-01/ 22
...
但是,我想知道,如何包含第二列 (columB) 中的信息,以便我看到在 2015-03-01 总共创建了十个帐户,但是例如三个它们已被修改。
是否需要第二个查询,或者可以在同一个查询中完成吗?
使用 lateral join
逆透视数据并聚合:
select gs.dd,
sum(v.is_create) as create_on_date,
sum(v.is_update) as update_on_day,
sum(sum(v.is_create)) over (order by gs.dd) as running_creates,
sum(sum(v.is_update)) over (order by gs.dd) as running_updates
from generate_series('2015-01-01'::timestamp,'2019-11-01'::timestamp,'1 month'::interval
) gs(dd) left join
(tb cross join lateral
(values (tb.updatedon, 0, 1), (createdon, 1, 0)
) v(dte, is_update, is_create)
)
on v.dte::date = dd::date
group by gs.dd
order by gs.dd;
请注意,这不会在 on
子句中使用不等式。相反,它使用 select
中的累计和。一般来说,从性能的角度来看,这是更可取的。
如果 updatedon
可以是 null
,您可能想要添加 where v.dte is not null
。
关于你的回答。
非常感谢你。
我已经完成了横向连接。
select gs.dd,
sum(v.is_create) as create_on_date,
sum(v.is_update) as update_on_day,
sum(sum(v.is_create)) over (order by gs.dd) as running_creates,
sum(sum(v.is_update)) over (order by gs.dd) as running_updates
from generate_series('2015-01-01'::timestamp,'2019-11-01'::timestamp,'1 month'::interval
) gs(dd) left join
(tb cross join lateral
(values (tb.creation_date, 0, 1), (tb.modification_date, 1, 0)
) v(dte, is_update, is_create)
)
on v.dte::date = dd::date
where v.dte is not null
and tb.gather_stats is not false
group by gs.dd
order by gs.dd;
现在我得到以下 table
Screenshot with data output
修改日期实际上可以是 null
,但不幸的是创建日期也可以是 null
。
查看原始数据,例如有两条记录,修改日期为2017年12月(创建日期为null
)。
原始数据显示在 2018 年 1 月至少创建了一个帐户,但未显示执行此横向连接。
我有一个 table (tb1),其中包含一个包含创建日期(A 列)和修改日期(B 列)的列。
我想要一个聚合度量值,显示在给定时间间隔内创建了多少记录,在同一时间间隔内修改了多少记录。
到目前为止,我已经尝试了以下代码:
Select count(distinct tb.id),dd
from generate_series ('2015-01-01'::timestamp,'2019-11-01'::timestamp,'1 month'::interval)dd
left join tb on tb.columnA<=dd::date
group by dd
我收到的输出很好,因为我得到了以下 table
dd/count
2015-01-01/ 2
2015-02-01/ 6
2015-03-01/ 10
2015-04-01/ 22
...
但是,我想知道,如何包含第二列 (columB) 中的信息,以便我看到在 2015-03-01 总共创建了十个帐户,但是例如三个它们已被修改。
是否需要第二个查询,或者可以在同一个查询中完成吗?
使用 lateral join
逆透视数据并聚合:
select gs.dd,
sum(v.is_create) as create_on_date,
sum(v.is_update) as update_on_day,
sum(sum(v.is_create)) over (order by gs.dd) as running_creates,
sum(sum(v.is_update)) over (order by gs.dd) as running_updates
from generate_series('2015-01-01'::timestamp,'2019-11-01'::timestamp,'1 month'::interval
) gs(dd) left join
(tb cross join lateral
(values (tb.updatedon, 0, 1), (createdon, 1, 0)
) v(dte, is_update, is_create)
)
on v.dte::date = dd::date
group by gs.dd
order by gs.dd;
请注意,这不会在 on
子句中使用不等式。相反,它使用 select
中的累计和。一般来说,从性能的角度来看,这是更可取的。
如果 updatedon
可以是 null
,您可能想要添加 where v.dte is not null
。
关于你的回答。 非常感谢你。
我已经完成了横向连接。
select gs.dd,
sum(v.is_create) as create_on_date,
sum(v.is_update) as update_on_day,
sum(sum(v.is_create)) over (order by gs.dd) as running_creates,
sum(sum(v.is_update)) over (order by gs.dd) as running_updates
from generate_series('2015-01-01'::timestamp,'2019-11-01'::timestamp,'1 month'::interval
) gs(dd) left join
(tb cross join lateral
(values (tb.creation_date, 0, 1), (tb.modification_date, 1, 0)
) v(dte, is_update, is_create)
)
on v.dte::date = dd::date
where v.dte is not null
and tb.gather_stats is not false
group by gs.dd
order by gs.dd;
现在我得到以下 table
Screenshot with data output
修改日期实际上可以是 null
,但不幸的是创建日期也可以是 null
。
查看原始数据,例如有两条记录,修改日期为2017年12月(创建日期为null
)。
原始数据显示在 2018 年 1 月至少创建了一个帐户,但未显示执行此横向连接。