简体   繁体   English

如何获取 postgreSQL 中条件的最后一个值?

[英]How to get last value with condition in postgreSQL?

I have a table in postgres with three columns, one with a group, one with a date and the last with a value.我在 postgres 中有一个包含三列的表,一列带有组,一列带有日期,最后一列带有值。

grp grp mydate我的约会 value价值
A一个 2021-01-27 2021-01-27 5 5
A一个 2021-01-23 2021-01-23 10 10
A一个 2021-01-15 2021-01-15 15 15
B 2021-01-26 2021-01-26 7 7
B 2021-01-24 2021-01-24 12 12
B 2021-01-15 2021-01-15 17 17

I would like to create a view with a sequence of dates and the most recent value on table for each date according with group.我想根据组创建一个包含一系列日期和表上每个日期的最新值的视图。

grp grp mydate我的约会 value价值
A一个 2021-01-27 2021-01-27 5 5
A一个 2021-01-26 2021-01-26 10 10
A一个 2021-01-25 2021-01-25 10 10
A一个 2021-01-24 2021-01-24 10 10
A一个 2021-01-23 2021-01-23 10 10
A一个 2021-01-22 2021-01-22 15 15
A一个 2021-01-21 2021-01-21 15 15
A一个 2021-01-20 2021-01-20 15 15
A一个 2021-01-19 2021-01-19 15 15
A一个 2021-01-18 2021-01-18 15 15
A一个 2021-01-17 2021-01-17 15 15
A一个 2021-01-16 2021-01-16 15 15
A一个 2021-01-15 2021-01-15 15 15
B 2021-01-27 2021-01-27 7 7
B 2021-01-26 2021-01-26 7 7
B 2021-01-25 2021-01-25 12 12
B 2021-01-24 2021-01-24 12 12
B 2021-01-23 2021-01-23 17 17
B 2021-01-22 2021-01-22 17 17
B 2021-01-21 2021-01-21 17 17
B 2021-01-20 2021-01-20 17 17
B 2021-01-19 2021-01-19 17 17
B 2021-01-18 2021-01-18 17 17
B 2021-01-17 2021-01-17 17 17
B 2021-01-16 2021-01-16 17 17
B 2021-01-15 2021-01-15 17 17

SQL code to generate the table: SQL代码生成表:

CREATE TABLE foo (
    grp char(1),
    mydate date,
    value integer);

INSERT INTO foo VALUES
('A', '2021-01-27', 5),
('A', '2021-01-23', 10),
('A', '2021-01-15', 15),
('B', '2021-01-26', 7),
('B', '2021-01-24', 12),
('B', '2021-01-15', 17)

I have so far managed to generate a visualization with the sequence of dates joined with the distinct groups, but I am failing to get the most recent value.到目前为止,我已经成功地生成了一个带有不同组的日期序列的可视化,但是我没有得到最新的值。

SELECT DISTINCT(foo.grp), (date_trunc('day'::text, dd.dd))::date AS mydate
   FROM foo, generate_series((( SELECT min(foo.mydate) AS min
           FROM foo))::timestamp without time zone, (now())::timestamp without time zone, '1 day'::interval) dd(dd)  

step-by-step demo:db<>fiddle 分步演示:db<>fiddle

SELECT
    grp,
    gs::date as mydate,
    value
FROM (
    SELECT
        *,
        COALESCE(                                                             -- 2
             lead(mydate) OVER (PARTITION BY grp ORDER BY mydate) - 1,        -- 1 
             mydate
        ) as prev_date
    FROM foo
) s,
    generate_series(mydate, prev_date, interval '-1 day') as gs               -- 3
ORDER BY grp, mydate DESC                                                     -- 4
  1. lead() window function shifts the next value of an ordered group (= partition) into the current one.lead() window function将有序组(=分区)的下一个值移动到当前值。 The group is already defined, the order is the date .组已定义,顺序为date This can be used to create the required date range.这可用于创建所需的日期范围。 Since you don't want to have the last date twice (as end of the first range and beginning of the next one) the end date stops - 1 (one day before the next group starts)由于您不希望最后一个日期有两次(作为第一个范围的结束和下一个范围的开始),因此结束日期停止- 1 (下一组开始前一天)
  2. This is for the very last records of the groups: They don't have a following record, so lead() yield NULL .这是组的最后记录:他们没有以下记录,因此lead()产生NULL To avoid this, COALESCE() sets them to the current record.为了避免这种情况, COALESCE()将它们设置为当前记录。
  3. Now, you can create a date range with the current and the next date value using generate_series() .现在,您可以使用generate_series()创建具有当前和下一个日期值的日期范围。
  4. Finally you can generate the required order最后就可以生成需要的订单了

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

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