如何通过分组和排序在 PostgreSQL 中填充空值

How to fill null values in PostgreSQL with grouping and ordering

假设我有以下数据:

+---------------------+---------+---------------------+
| date                | tokenId | last_price          |
|---------------------+---------+---------------------|
| 2021-07-01 00:00:00 | 1       | <null>              |
| 2021-08-01 00:00:00 | 1       | 5.0                 |
| 2021-09-01 00:00:00 | 1       | <null>              |
| 2021-10-01 00:00:00 | 1       | <null>              |
| 2021-11-01 00:00:00 | 1       | 4.6000000000000005  |
| 2021-12-01 00:00:00 | 1       | <null>              |
| 2022-01-01 00:00:00 | 1       | <null>              |
| 2022-02-01 00:00:00 | 1       | <null>              |
| 2022-03-01 00:00:00 | 1       | <null>              |
| 2022-04-01 00:00:00 | 1       | <null>              |
| 2022-05-01 00:00:00 | 1       | <null>              |
| 2021-07-01 00:00:00 | 18      | 0.09200000000000001 |
| 2021-08-01 00:00:00 | 18      | <null>              |
| 2021-09-01 00:00:00 | 18      | <null>              |
| 2021-10-01 00:00:00 | 18      | <null>              |
| 2021-11-01 00:00:00 | 18      | 7.6000000000000005  |
| 2021-12-01 00:00:00 | 18      | <null>              |
| 2022-01-01 00:00:00 | 18      | 15.200000000000001  |
| 2022-02-01 00:00:00 | 18      | <null>              |
| 2022-03-01 00:00:00 | 18      | <null>              |
| 2022-04-01 00:00:00 | 18      | <null>              |
| 2022-05-01 00:00:00 | 18      | <null>              |
+---------------------+---------+---------------------+

我怎样才能像这样用前几行中每个代币的最后价格填充空行:

+---------------------+---------+---------------------+
| date                | tokenId | last_price          |
|---------------------+---------+---------------------|
| 2021-07-01 00:00:00 | 1       | <null>              |
| 2021-08-01 00:00:00 | 1       | 5.0                 |
| 2021-09-01 00:00:00 | 1       | 5.0                 |
| 2021-10-01 00:00:00 | 1       | 5.0                 |
| 2021-11-01 00:00:00 | 1       | 4.6000000000000005  |
| 2021-12-01 00:00:00 | 1       | 4.6000000000000005  |
| 2022-01-01 00:00:00 | 1       | 4.6000000000000005  |
| 2022-02-01 00:00:00 | 1       | 4.6000000000000005  |
| 2022-03-01 00:00:00 | 1       | 4.6000000000000005  |
| 2022-04-01 00:00:00 | 1       | 4.6000000000000005  |
| 2022-05-01 00:00:00 | 1       | 4.6000000000000005  |
| 2021-07-01 00:00:00 | 18      | 0.09200000000000001 |
| 2021-08-01 00:00:00 | 18      | 0.09200000000000001 |
| 2021-09-01 00:00:00 | 18      | 0.09200000000000001 |
| 2021-10-01 00:00:00 | 18      | 0.09200000000000001 |
| 2021-11-01 00:00:00 | 18      | 7.6000000000000005  |
| 2021-12-01 00:00:00 | 18      | 7.6000000000000005  |
| 2022-01-01 00:00:00 | 18      | 15.200000000000001  |
| 2022-02-01 00:00:00 | 18      | 15.200000000000001  |
| 2022-03-01 00:00:00 | 18      | 15.200000000000001  |
| 2022-04-01 00:00:00 | 18      | 15.200000000000001  |
| 2022-05-01 00:00:00 | 18      | 15.200000000000001  |
+---------------------+---------+---------------------+

我找到了关于类似问题 here 的一些很好的答案,但我不明白如何通过 tokenId 字段进行额外分组来使用它。

一个可能的解决方案是:

SELECT a_date, tokenId, last_price,
       (SELECT last_price
        FROM   A_TABLE 
        WHERE  a_date = (SELECT MAX(a_date) 
                         FROM   A_TABLE AS A 
                         WHERE  A.a_date <= T.a_date AND last_price IS NOT NULL))
FROM   A_TABLE AS T

其他一些使用窗口函数

你可以使用横向。即:

select t1.date, t1.tokenid, coalesce(t1.last_price, p.last_price) last_price 
from myTable t1
left join lateral(select last_price 
                        from myTable t2
                        where t1.tokenId = t2.tokenId and t1.date > t2.date
                           and t2.last_price is not null
                        order by t2.date desc
                        limit 1) p on true
order by t1.tokenId, t1.date;