Postgresql Fill Gaps - 给定分支的最新可用信息矩阵

Postgresql Fill Gaps - Matrix of latest available information for a given branch

我有一个 table,其中包含导入文件的索引,以及每个导入文件的日期和分支。

现在需要做多个分行的合并,所以放假的时候要复制一些分行的信息,这样数据才一致,基本上我需要用最新的来填补这些空缺可用信息。

我尝试使用排名进行一些自连接,以便在它们之间切换并获取以前的数据,但没有成功。

我有一个 table:

rundate, branch, imported 
2015-04-01, PL1, TRUE 
2015-04-01, ES1, TRUE 
2015-04-01, CZ4, TRUE 
2015-04-02, PL1, TRUE 
2015-04-02, ES1, TRUE 
2015-04-02, CZ4, TRUE   
2015-04-03, ES1, TRUE 
2015-04-03, CZ4, TRUE

在这个例子中,我想查询 returns:

gap_date, branch, real_date
2015-04-03, PL1, 2015-04-02

这个 table 非常小(几千行),因此,性能应该不是大问题。

知道如何实现吗?

现在我正在使用一个函数,它接收间隙日期的运行日期和分支作为参数,并回答作为参数传递的日期之前的最新消息(使用 max(rundate) where rundate <= '$1')

谢谢!

您必须 select 一组中的所有唯一日期,另一组中的所有唯一分支 - 对其进行笛卡尔积 - 然后您可以检查哪个组合存在差距...这是我的意思是:

CREATE TEMPORARY TABLE _matrix
SELECT
t1.rundate,
t2.branch
(SELECT DISTINCT rundate FROM yourtable) t1,
(SELECT DISTINCT branch FROM yourtable) t2

然后您可以使用 LEFT JOIN 和 "WHERE ... IS NULL" 语句找到间隙:

SELECT
m.rundate,
m.branch
FROM _matrix m
LEFT JOIN yourtable yt ON(yt.rundate = m.rundate AND yt.branch = m.branch)
WHERE yt.rundate IS NULL

当然,没有临时表也可以实现同样的效果——只使用一个子查询。尤其是当性能不是关键的时候。

您可以使用 outer joinsubquerycross join:

架构:

create table tbl(rundate date, 
                 branch varchar(10), 
                 imported bool);
insert into tbl values('2015-04-01', 'PL1', TRUE),
('2015-04-01', 'ES1', TRUE), 
('2015-04-01', 'CZ4', TRUE), 
('2015-04-02', 'PL1', TRUE), 
('2015-04-02', 'ES1', TRUE), 
('2015-04-02', 'CZ4', TRUE),  
('2015-04-03', 'ES1', TRUE), 
('2015-04-03', 'CZ4', TRUE); 

查询:

select q.rundate as gap_date,q.branch,
       (select max(tt.rundate) 
        from tbl tt
        where tt.rundate<q.rundate and tt.branch=q.branch)
        as real_date
from tbl t
right outer join(
         select rundate,branch from (
                select distinct rundate from tbl) t1
                cross join (
                select distinct branch from tbl)t2
          )q 
on t.rundate=q.rundate and t.branch=q.branch
where t.branch is null

结果:

gap_date    branch  real_date
2015-04-03  PL1     2015-04-02

这是来自@voycheck carthesian product of both domains解决方案,除了实际存在的记录。

WITH br AS (
        SELECT DISTINCT branch AS branch FROM tbl
        )
, mima AS (
        SELECT MIN(rundate) as mi
             , MAX(rundate) as ma
        FROM tbl)
, rng AS (
        SELECT generate_series( mima.mi, mima.ma, '1 day'::interval)::date AS rundate
        FROM mima
        )
SELECT * FROM rng
JOIN br ON NOT EXISTS ( -- cartesian product EXCEPT
        SELECT *
        FROM tbl t
        WHERE t.branch = br.branch
        AND t.rundate = rng.rundate
        )
        ;