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 join
、subquery
和 cross 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
)
;
我有一个 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 join
、subquery
和 cross 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
)
;