简体   繁体   English

使用 postgresql 中的顺序日期将数据宽转换为长

[英]convert data wide to long with make sequential date in postgresql

I have data frame with date like below:我有如下日期的数据框:

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

I want make this data wide to long like:我想让这些数据变得很长,比如:

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

give me some idea please请给我一些想法

For Oracle 12c and later, you can use:对于 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

Which, for the sample data:其中,对于样本数据:

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;

Outputs:输出:

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

db<>fiddle here db<> 在这里摆弄

In Postgres you can use generate_series() for this:在 Postgres 中,您可以为此使用generate_series()

select t.id, g.day::date as date, t.product, t.supply_per_day
from the_table t
  cross join generate_series(t.start_date, t.end_date, interval '1 day') as g(day)
order by t.id, g.day  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM