Postgresql

將多個時間線的兩個事件表合併到一個結果集中

  • July 9, 2015

這個問題是我之前提出的一個過於簡化的問題的擴展。這個 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 ');

每個表都有時間線“A”和“B”的事件。目標是將結果組合到一個結果集中,顯示每個時間線的“狀態”。兩條時間線是正交的。

ts id 富吧
1 客戶
5. 客戶是
6 坐 sed
8 擁抱
1 B 本身(空)
4 B dolor(空)
5 B 止痛藥
8乙
9 B 做

除了簡單案例的解決方案外,在內部查詢中的視窗函式中添加一個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;

結果按要求(id第一個除外)。

SQL小提琴

您嘗試適應以前的解決方案非常接近。由於PARTITION BY f.id/PARTITION BY b.id而不是PARTITION BY id. 您真的希望組合 id在結果中包含缺失的行 - 這就是必須為缺失 (NULL) 值填寫最後一個非空值的地方。

如果性能是您的首要要求,請考慮使用上一個答案中展示的伺服器端功能。

引用自:https://dba.stackexchange.com/questions/106514