dt

问题描述 投票:1回答:1

我有一个表。

 ╔════════════╦════════╦════════════╗
 ║ product_id ║ amount ║ date       ║
 ╠════════════╬════════╬════════════╣
 ║ 1          ║ 100    ║ 2019-01-01 ║
 ║ 2          ║ 150    ║ 2019-01-01 ║
 ║ 1          ║ 200    ║ 2019-01-05 ║
 ║ 2          ║ 180    ║ 2019-01-03 ║
 ║ 2          ║ 150    ║ 2019-01-05 ║
 ╚════════════╩════════╩════════════╝

我需要根据下一行的值(金额)来生成产品的行。我需要这样的结果。

╔════════════╦════════╦════════════╗
║ product_id ║ amount ║ date       ║
╠════════════╬════════╬════════════╣
║ 1          ║ 100    ║ 2019-01-01 ║
║ 1          ║ 100    ║ 2019-01-02 ║
║ 1          ║ 100    ║ 2019-01-03 ║
║ 1          ║ 100    ║ 2019-01-04 ║
║ 1          ║ 200    ║ 2019-01-05 ║
║ 2          ║ 150    ║ 2019-01-01 ║
║ 2          ║ 150    ║ 2019-01-02 ║
║ 2          ║ 180    ║ 2019-01-03 ║
║ 2          ║ 180    ║ 2019-01-04 ║
║ 2          ║ 150    ║ 2019-01-05 ║
╚════════════╩════════╩════════════╝
sql postgresql date group-by gaps-and-islands
1个回答
1
投票

您可以使用 generate_series() 在一个聚合子查询中生成 "丢失 "的日期。

然后,我们需要在新的行中加入前面的非空量--如果Postgres支持这个功能,这将是直接的。ignore nulls 选择 lag() - 但它没有。解决这个问题的一个方法是使用一个窗口数来定义组,然后使用 firstvalue()`。

select
    product_id, 
    dt,
    first_value(amount) over(partition by product_id, grp order by dt) amount
from (
    select 
        x.*, 
        t.amount,
        count(*) filter(where t.amount is not null) 
            over(partition by x.product_id order by x.dt) grp
    from (
        select product_id, generate_series(min(date), max(date), '1 day'::interval) dt
        from mytable
        group by product_id
    ) x
    left join mytable t on t.product_id = x.product_id and t.date = x.dt
) t
order by product_id, dt

DB Fiddle上的演示:

产品ID 
© www.soinside.com 2019 - 2024. All rights reserved.