SQL:列出行之间的差异(显示在列中)

时间:2018-12-11 14:05:29

标签: sql oracle sybase

我有一个这样的桌子

ID   |  FatherID     |   A   |  B    |   C   |     D        | ...
1234 |     -1        |  John | Doe   |   15  |   20181211   | ...
5678 |     -1        |  Mark | Bloch |   34  |   20170804   | ...
4554 |     1234      |  John | Dee   |   25  |   20181211   | ...
2457 |     5678      |  Chris| Bloch |   34  |   20180402   | ...

如果对给定对象进行了修改(例如ID 1234),则系统会参考原始ID(FatherID = 1234)将新版本数据存储在新ID(例如4554)上。 系统仅存储初始版本和主要修订(最后修改),例如,如果最终再次修改4554,则不会创建新记录,但会更新4554值->每个ID最多2条记录

有很多列(大约400列)...

我想以这样的格式列出所做的修改:

ID   | Field | Before       | After
4554 |  B    | Doe          | Dee
4554 |  C    | 15           | 25
2457 |  A    | Mark         | Chris
4554 |  D    | 20170804     | 20180402

我正在努力做到这一点,特别是考虑到列数。

任何帮助将不胜感激!

非常感谢

2 个答案:

答案 0 :(得分:0)

  

有很多列(大约400列)...

仅向您介绍一下仅检查4列的情况(这是针对Oracle):

WITH full AS (
  SELECT 
    o.ID, 
    o.A, o.B, o.C, o.D, 
    n.A AS newA, n.B AS newB, n.C AS newC, n.D AS newD 
  FROM tablename o 
  INNER JOIN tablename n ON n.FatherID = o.ID
  WHERE o.FatherID = -1
)

SELECT ID, Field, Before, After FROM(
  SELECT 
    ID,
    'A' As Field,
    CASE WHEN A <> newA THEN 1 ELSE 0 END AS changed,
    A AS Before,
    newA AS After
  FROM full
  UNION
  SELECT 
    ID,
    'B' As Field,
    CASE WHEN B <> newB THEN 1 ELSE 0 END AS changed,
    B AS Before,
    newB AS After
  FROM full
  UNION
  SELECT 
    ID,
    'C' As Field,
    CASE WHEN C <> newC THEN 1 ELSE 0 END AS changed,
    C AS Before,
    newC AS After
  FROM full
  UNION
  SELECT 
    ID,
    'D' As Field,
    CASE WHEN D <> newD THEN 1 ELSE 0 END AS changed,
    D AS Before,
    newD AS After
  FROM full
)  
WHERE changed = 1

答案 1 :(得分:0)

您可以取消对配对列的过滤,并仅过滤不同的列。

select id, fatherid, field, o before, n after 
  from (
    select n.id, n.fatherid, n.a na, o.a oa, n.b nb, o.b ob, 
           to_char(n.c) nc, to_char(o.c) oc, 
           to_char(n.d) nd, to_char(o.d) od
      from t n join t o on n.fatherid = o.id)
  unpivot ((n, o) for field in ((na, oa) as 'A', (nb, ob) as 'B', 
                                (nc, oc) as 'C', (nd, od) as 'D'))
  where n <> o or (n is null and o is not null) or (n is not null and o is null)
  order by id, field

demo with your sample data

    ID   FATHERID  FIELD  BEFORE    AFTER
------  ---------  -----  --------  -----------
  2457       5678  A      Mark      Chris
  2457       5678  D      20170804  20180402
  4554       1234  B      Doe       Dee
  4554       1234  C      15        25

您必须列出所有列,并将它们转换为char。很多工作,很多错误空间,但这是我想出的最好的方法。