【问题标题】:Postgres auto insert with previous values if some data misses如果某些数据丢失,Postgres 会自动插入以前的值
【发布时间】:2020-11-27 12:35:34
【问题描述】:

我有日期范围的数据,有些日期几天都不会出现,在错过的窗口期间我只想插入以前的数据。

有没有办法在自己插入数据时处理这个问题

例如

create table foo (ID VARCHAR(10), foo_count int, actual_date date);
insert into foo ( values('234534', 100, '2017-01-01'),('234534', 200, '2017-01-02'));   
insert into foo ( values('234534', 300, '2017-01-03') );
insert into foo ( values('234534', 300, '2017-01-08') );

在最后一次插入之后,我可以确保生成以前的数据

所以它应该看起来像这样

 ID        | foo_count       | actual_date
-----------+-----------------+------------
 234534    | 100             | 2017-01-01
 234534    | 200             | 2017-02-01
 234534    | 300             | 2017-03-01
 234534    | 300             | 2017-04-01
 234534    | 300             | 2017-05-01
 234534    | 300             | 2017-06-01
 234534    | 180             | 2017-07-01

我正在使用 JPA 插入它,目前我查询表并查看表中的当前日期并填充缺失的数据

【问题讨论】:

    标签: postgresql hibernate spring-data-jpa


    【解决方案1】:

    我会考虑一个更好的INSERT 声明。从SELECT 语句插入会使事情变得更容易。 SELECT 语句可用于生成请求的日期系列。

    INSERT INTO foo
    SELECT
        --<advanced query>
    

    但是,我想这不是简单的可能,因为您没有直接使用 JDBC 或想要使用本机查询来插入数据。

    在这种情况下,您可以在数据库中安装一个触发器,它可以发挥神奇的作用:

    demo:db<>fiddle

    触发功能:

    CREATE FUNCTION insert_missing()
        RETURNS TRIGGER AS
    $$
    DECLARE
        max_record record;
    BEGIN
        SELECT                                                       -- 1
            id,
            foo_count,
            actual_date
        FROM
            foo
        ORDER BY actual_date DESC
        LIMIT 1
        INTO max_record;
    
        IF (NEW.actual_date - 1 > max_record.actual_date) THEN       -- 2
            INSERT INTO foo
            SELECT 
                max_record.id,
                max_record.foo_count,
                generate_series(max_record.actual_date + 1, NEW.actual_date - 1,  interval '1 day');  -- 3
        END IF;
    
        RETURN NEW;
    END;
    $$ language 'plpgsql';
    
    1. 查询当前最大日期的记录。
    2. 如果最大日期比新日期早一天...
    3. ... 插入日期系列(从当前最大日期之后的一天到新日期之前的日期)。这可以使用generate_series() 生成。

    然后创建ON BEFORE INSERT 触发器:

    CREATE TRIGGER insert_missing
      BEFORE INSERT
      ON foo
      FOR EACH ROW
      EXECUTE PROCEDURE insert_missing();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-27
      相关资源
      最近更新 更多