将多个时间线的两个事件表合并为一个结果集

Chr*_*rie 5 postgresql join window-functions

这个问题是我之前提出的一个过于简化的问题的扩展。更准确的示例在此 SQLFiddle中演示,我演示了一个有效(但速度较慢)的解决方案,然后尝试将先前的答案调整为实际问题。

实际问题是因为这两个表包含多个时间线的事件。

CREATE TABLE foo (ts int, id text, foo text);
INSERT INTO foo (ts, id, foo)
VALUES
    (1, 'A', 'Lorem'),
    (1, 'B', 'ipsum'),
    (4, 'B', 'dolor'),
    (5, 'A', 'sit'),
    (8, 'A', 'amet'),
    (8, 'B', 'consectetur');

CREATE TABLE bar (ts int, id text, bar text);
INSERT INTO bar (ts, id, bar)
VALUES
    (1, 'A', 'adipiscing'),
    (5, 'B', 'elit'),
    (6, 'A', 'sed'),
    (9, 'B', 'do ');
Run Code Online (Sandbox Code Playgroud)

每个表都有时间线“A”和“B”的事件。目标是将结果组合成单个结果集,显示每个时间线的“状态”。两条时间线是正交的。

ts id foo 栏
1 Lorem adipiscing
5 坐姿
6 A坐sed
8 Amet sed
1 B ipsum(空)
4 Bdolor(空)
5 B多洛尔精英
8 B consectetur 精英
9 B consectetur do

Erw*_*ter 4

除了简单情况的解决方案之外,还在PARTITION内部查询中的窗口函数中添加一个子句,以获取每个分区(每个“时间线”)的组编号。将组编号与相应的时间线(id在您的示例中)结合起来,在第二步中保持分区分开:

SELECT id, ts
     , min(foo) OVER (PARTITION BY id, foo_grp) AS foo
     , min(bar) OVER (PARTITION BY id, bar_grp) AS bar
FROM (
   SELECT id, ts, f.foo, b.bar
        , count(f.foo) OVER (PARTITION BY id ORDER BY ts) AS foo_grp
        , count(b.bar) OVER (PARTITION BY id ORDER BY ts) AS bar_grp
   FROM   foo f
   FULL   JOIN bar b USING (id, ts)
   ) sub
ORDER  BY 1, 2;
Run Code Online (Sandbox Code Playgroud)

结果按要求(第一个除外id)。
SQL小提琴

您对先前解决方案的尝试非常接近。它不起作用,因为PARTITION BY f.id/PARTITION BY b.id而不是PARTITION BY id。您确实希望组合 id结果中包含缺失的行 - 这就是必须为缺失 (NULL) 值填充最后一个非空值的位置。

如果性能是您的首要要求,请考虑使用服务器端功能,如上一个答案中所示