爆炸sql表并为不存在的每一天插入一行

时间:2016-07-29 20:00:14

标签: sql postgresql

我有一个像这样的表,我通过适度的重新加工this数据+ SQL来生成白天显示,但我想在空的日子里加上右边的运行记录。

╔════════════╦════════╦═════════╦════════╗
║ day        ║ num1   ║ num2    ║ tally  ║
╠════════════╬════════╬═════════╬════════╣
║ 2016-06-10 ║   9.99 ║         ║   9.99 ║
║ 2016-06-12 ║ 136.00 ║    9.99 ║ 145.99 ║
║ 2016-06-14 ║        ║  145.99 ║ 145.99 ║
║ 2016-06-18 ║   9.99 ║  145.99 ║ 155.98 ║
║ 2016-06-19 ║ 210.00 ║  145.99 ║ 365.98 ║
║ 2016-06-22 ║  50.00 ║    9.99 ║ 279.98 ║
║ 2016-06-28 ║  69.99 ║   59.99 ║ 349.97 ║
╚════════════╩════════╩═════════╩════════╝

我不知道如何制作它以便表转换为:

╔════════════╦════════╦═════════╦════════╗
║ day        ║ num1   ║ num2    ║ tally  ║
╠════════════╬════════╬═════════╬════════╣
║ 2016-06-10 ║   9.99 ║         ║   9.99 ║
║ 2016-06-11 ║        ║         ║   9.99 ║ <- new row with previous value
║ 2016-06-12 ║ 136.00 ║    9.99 ║ 145.99 ║
║ 2016-06-13 ║        ║         ║ 145.99 ║ <- new row with previous value
║ 2016-06-14 ║        ║  145.99 ║ 145.99 ║
║ 2016-06-15 ║        ║         ║ 145.99 ║ <- new row with previous value
║ 2016-06-16 ║        ║         ║ 145.99 ║ <- new row with previous value
║ 2016-06-17 ║        ║         ║ 145.99 ║ <- new row with previous value
║ 2016-06-18 ║   9.99 ║  145.99 ║ 155.98 ║
║ 2016-06-19 ║ 210.00 ║  145.99 ║ 365.98 ║
║ 2016-06-20 ║        ║         ║ 365.98 ║ <- new row with previous value
║ 2016-06-21 ║        ║         ║ 365.98 ║ <- new row with previous value
║ 2016-06-22 ║  50.00 ║    9.99 ║ 279.98 ║
║ 2016-06-23 ║        ║         ║ 279.98 ║ <- new row with previous value
║ 2016-06-24 ║        ║         ║ 279.98 ║ <- new row with previous value
║ 2016-06-25 ║        ║         ║ 279.98 ║ <- new row with previous value
║ 2016-06-26 ║        ║         ║ 279.98 ║ <- new row with previous value
║ 2016-06-27 ║        ║         ║ 279.98 ║ <- new row with previous value
║ 2016-06-28 ║  69.99 ║   59.99 ║ 349.97 ║
╚════════════╩════════╩═════════╩════════╝

2 个答案:

答案 0 :(得分:1)

尝试一下(我假设您的表名为tbl)。我使用generate_series生成缺少的行,并使用几个窗口函数在新行中插入相应的tally值。

with all_dates as (
  SELECT day
   FROM generate_series
        ('2016-06-10'::date,
         '2016-06-28'::date,
         '1 day'::interval) day
), partitioned_data as (
  select d.day, t.num1, t.num2, t.tally,
         sum(case when t.tally is not null then 1 else 0 end) over (order by d.day) as partition_id
    from all_dates d
    left join tbl t
      on t.day = d.day
)
select t.day, t.num1, t.num2,
       first_value(t.tally) over (partition by t.partition_id) as tally
  from partitioned_data t
 order by t.day

答案 1 :(得分:1)

数据:

create table the_data(day date, num1 numeric, num2 numeric, tally numeric);
insert into the_data values
('2016-06-10', 9.99, null, 9.99),
('2016-06-12', 136.00, 9.99, 145.99),
('2016-06-14', null, 145.99, 145.99),
('2016-06-18', 9.99, 145.99, 155.98),
('2016-06-19', 210.00, 145.99, 365.98),
('2016-06-22', 50.00, 9.99, 279.98),
('2016-06-28', 69.99, 59.99, 349.97);

查询:

with the_data as (  
    select d::date as day, num1, num2, tally
    from generate_series('2016-06-10'::date, '2016-06-28', '1d') d
    left join the_data on d = day
    )
select distinct on (a.day) a.day, a.num1, a.num2, b.tally
from the_data a
join the_data b
on a.day >= b.day and b.tally is not null
order by a.day, b.day desc;

    day     |  num1  |  num2  | tally  
------------+--------+--------+--------
 2016-06-10 |   9.99 |        |   9.99
 2016-06-11 |        |        |   9.99
 2016-06-12 | 136.00 |   9.99 | 145.99
 2016-06-13 |        |        | 145.99
 2016-06-14 |        | 145.99 | 145.99
 2016-06-15 |        |        | 145.99
 2016-06-16 |        |        | 145.99
 2016-06-17 |        |        | 145.99
 2016-06-18 |   9.99 | 145.99 | 155.98
 2016-06-19 | 210.00 | 145.99 | 365.98
 2016-06-20 |        |        | 365.98
 2016-06-21 |        |        | 365.98
 2016-06-22 |  50.00 |   9.99 | 279.98
 2016-06-23 |        |        | 279.98
 2016-06-24 |        |        | 279.98
 2016-06-25 |        |        | 279.98
 2016-06-26 |        |        | 279.98
 2016-06-27 |        |        | 279.98
 2016-06-28 |  69.99 |  59.99 | 349.97
(19 rows)