2016-12-05 25 views
0

私は20列のような履歴テーブルを持っており、どの列と値が変更されたのかを知る必要があります。私はこのクエリを実行しました:PostgreSQL - 値の変更が最適化された列を選択

(SELECT id, rev, col1 as "val", CASE WHEN TRUE THEN 'col1'END "field" 
     FROM (SELECT id, col1, rev, LAG(col1) 
       OVER (ORDER BY rev) AS prev_col1 
       FROM my_table) x 
    WHERE id = 82 
     AND col1 <> COALESCE(prev_col1, col1) 
    ORDER BY rev) 
    UNION 
    (SELECT id, rev, col2 as "val", 
    CASE WHEN TRUE THEN 'col2'END "field" 
     FROM (SELECT id, col2, rev, LAG(col2) 
       OVER (ORDER BY rev) AS prev_col2 
       FROM my_table) x 
     WHERE id = 82 
     AND col2 <> COALESCE(prev_col2, col2) 
    ORDER BY rev) 
     UNION .... 

私はこれを行うためのよりよい方法を知りたいと思います。それはうまくいくが、うまく見えない。

編集

私はゴードンから少し仕事にSQLの答えを変更するには変更する必要がありました:

select id, rev, field, val 
    from (select v.*, 
       lag(v.val) over (partition by v.id, v.field order by v.rev) as prev_val 
      from ((select t.id, t.rev, 'col1' field, col1 val from my_table t) union all 
       (select t.id, t.rev, 'col2' field, col2 val from my_table t) union all 
       . . . 
       ) v 
      where v.id = 82 
     ) tv 
    where prev_val <> val or prev_val is null; 

答えて

3

私はあなたが行をアンピボットする必要があると思います。 union allを使わずにクエリを言い換えることができます。以下では、横方向がアンピボットのために参加しないと、単一select句でロジックを表現する:

select id, rev, field, val 
from (select t.id, t.rev, v.field, v.val, 
      lag(v.val) over (partition by t.id, v.field order by t.rev) as prev_val 
     from my_table t, lateral 
      (values ('col1', col1), 
        ('col2', col2), 
        . . . 
      ) v(field, val) 
     where t.id = 82 
    ) tv 
where prev_val <> val or prev_val is null; 

横のPostgres 9.3で導入された結合します。代わりに明示的にピボット解除することです:

select id, rev, field, val 
from (select t.*, 
      lag(v.val) over (partition by t.id, v.field order by t.rev) as prev_val 
     from ((select t.id, t.rev, 'col1', col1 from my_table t 
      ) union all 
      (select t.id, t.rev, 'col2', col2 from my_table t 
      ) union all 
      . . . 
      ) t 
     where t.id = 82 
    ) tv 
where prev_val <> val or prev_val is null; 
+0

それは私が必要としていたものでした、あなたに感謝ゴードン! – Sertage

関連する問題