Postgresql - min/max 组内的日期范围
Postgresql - min/max date range within group
我们有一个事务性 table 存储数据,就像历史数据 table 一样,只要状态发生变化(或其他属性),它就会生效。
示例:
Product | Status | Start Date | End Date
----------+------- --+------------+-----------
widget a | active | 02/01/2020 | 02/30/2020
widget a | active | 03/01/2020 | 03/19/2020
widget a | inactive | 03/20/2020 | 05/01/2020
widget a | active | 05/02/2020 | 08/31/2020
widget b | active | 02/01/2020 | 05/31/2020
widget b | inactive | 06/01/2020 | 06/31/2020
我正在尝试根据状态变化时的最小和最大日期汇总此数据(正如我所说,其他属性有助于记录变化,但我只关心状态变化)。因此,在上面的示例中,'widget a' 将有三个记录:从 02/01/2020 - 03/19/2020 开始活动,从 03/20/2020 - 05/01/2020 开始活动,从 05/02/2020 开始活动- 2020 年 8 月 31 日。这可以使用 ETL 工具轻松完成,但我想将其放入视图中。
在注意性能的同时执行此操作的最佳方法是什么
这是 postgresql 10
这是一个 gaps-and-islands 问题,您希望将具有相同产品和状态的相邻行组合在一起。
这是一种使用行号之间的差异来构建组的方法:
select product, status, min(start_date) start_date, max(end_date) end_date
from (
select t.*,
row_number() over(partition by product order by start_date) rn1,
row_number() over(partition by product, status order by start_date) rn2
from mytable t
) t
group by product, rn1 - rn2
我们有一个事务性 table 存储数据,就像历史数据 table 一样,只要状态发生变化(或其他属性),它就会生效。
示例:
Product | Status | Start Date | End Date
----------+------- --+------------+-----------
widget a | active | 02/01/2020 | 02/30/2020
widget a | active | 03/01/2020 | 03/19/2020
widget a | inactive | 03/20/2020 | 05/01/2020
widget a | active | 05/02/2020 | 08/31/2020
widget b | active | 02/01/2020 | 05/31/2020
widget b | inactive | 06/01/2020 | 06/31/2020
我正在尝试根据状态变化时的最小和最大日期汇总此数据(正如我所说,其他属性有助于记录变化,但我只关心状态变化)。因此,在上面的示例中,'widget a' 将有三个记录:从 02/01/2020 - 03/19/2020 开始活动,从 03/20/2020 - 05/01/2020 开始活动,从 05/02/2020 开始活动- 2020 年 8 月 31 日。这可以使用 ETL 工具轻松完成,但我想将其放入视图中。
在注意性能的同时执行此操作的最佳方法是什么
这是 postgresql 10
这是一个 gaps-and-islands 问题,您希望将具有相同产品和状态的相邻行组合在一起。
这是一种使用行号之间的差异来构建组的方法:
select product, status, min(start_date) start_date, max(end_date) end_date
from (
select t.*,
row_number() over(partition by product order by start_date) rn1,
row_number() over(partition by product, status order by start_date) rn2
from mytable t
) t
group by product, rn1 - rn2