首页 > 解决方案 > 使用postgresql中的顺序日期将数据宽转换为长

问题描述

我有如下日期的数据框:

id  start_date  end_date     product supply_per_day 
1   2020-03-01  2020-03-01      A            10
1   2020-03-01  2020-03-01      B            10
1   2020-03-01  2020-03-02      A             5
2   2020-02-28  2020-03-02      A            10
2   2020-03-01  2020-03-03      B             4
2   2020-03-02  2020-03-05      A             5

我想让这个数据宽到长,比如:

id        date  product  supply_per_day 
1   2020-03-01      A           10
1   2020-03-01      B           10
1   2020-03-01      A            5
1   2020-03-02      A            5
2   2020-02-28      A           10
2   2020-03-01      A           10
2   2020-03-02      A           10
2   2020-03-01      B            4
2   2020-03-02      B            4
2   2020-03-03      B            4
2   2020-03-02      B            5
2   2020-03-03      B            5
2   2020-03-04      B            5
2   2020-03-05      B            5

请给我一些想法

标签: sqlpostgresql

解决方案


对于 Oracle 12c 及更高版本,您可以使用:

SELECT t.id,
       d.dt,
       t.product,
       t.supply_per_day
FROM   table_name t
       OUTER APPLY(
         SELECT start_date + LEVEL - 1 AS dt
         FROM   DUAL
         CONNECT BY start_date + LEVEL - 1 <= end_date
       ) d

其中,对于样本数据:

CREATE TABLE table_name ( id, start_date, end_date, product, supply_per_day ) AS
SELECT 1, DATE '2020-03-01', DATE '2020-03-01', 'A', 10 FROM DUAL UNION ALL
SELECT 1, DATE '2020-03-01', DATE '2020-03-01', 'B', 10 FROM DUAL UNION ALL
SELECT 1, DATE '2020-03-01', DATE '2020-03-02', 'A',  5 FROM DUAL UNION ALL
SELECT 2, DATE '2020-02-28', DATE '2020-03-02', 'A', 10 FROM DUAL UNION ALL
SELECT 2, DATE '2020-03-01', DATE '2020-03-03', 'B',  4 FROM DUAL UNION ALL
SELECT 2, DATE '2020-03-02', DATE '2020-03-05', 'A',  5 FROM DUAL;

输出:

ID DT 产品 SUPPLY_PER_DAY
1 2020-03-01 00:00:00 一个 10
1 2020-03-01 00:00:00 10
1 2020-03-01 00:00:00 一个 5
1 2020-03-02 00:00:00 一个 5
2 2020-02-28 00:00:00 一个 10
2 2020-02-29 00:00:00 一个 10
2 2020-03-01 00:00:00 一个 10
2 2020-03-02 00:00:00 一个 10
2 2020-03-01 00:00:00 4
2 2020-03-02 00:00:00 4
2 2020-03-03 00:00:00 4
2 2020-03-02 00:00:00 一个 5
2 2020-03-03 00:00:00 一个 5
2 2020-03-04 00:00:00 一个 5
2 2020-03-05 00:00:00 一个 5

db<>在这里摆弄


推荐阅读