SQL :列出行之间的差异(显示在列中)
SQL : list differences between rows (showed in columns)
我有一个table这样的
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(例如 4554)上,并引用原始 ID(FatherID = 1234)。
系统只存储初始版本和 head revision(最后修改),例如如果 4554 最终再次修改,则不会创建新记录但会更新 4554 值 --> Max 2 records per ID
有很多列(大约 400)...
我想以这样的格式列出已完成的修改:
ID | Field | Before | After
4554 | B | Doe | Dee
4554 | C | 15 | 25
2457 | A | Mark | Chris
4554 | D | 20170804 | 20180402
我正在努力做到这一点,尤其是考虑到列数。
如有任何帮助,我们将不胜感激!
非常感谢
There are lots of columns (around 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
您可以逆透视成对的列并仅过滤不同的列。
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
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
您必须列出所有列,将它们转换为字符。很多工作,很多 space 的错误,但这是我想到的最好的。
我有一个table这样的
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(例如 4554)上,并引用原始 ID(FatherID = 1234)。 系统只存储初始版本和 head revision(最后修改),例如如果 4554 最终再次修改,则不会创建新记录但会更新 4554 值 --> Max 2 records per ID
有很多列(大约 400)...
我想以这样的格式列出已完成的修改:
ID | Field | Before | After
4554 | B | Doe | Dee
4554 | C | 15 | 25
2457 | A | Mark | Chris
4554 | D | 20170804 | 20180402
我正在努力做到这一点,尤其是考虑到列数。
如有任何帮助,我们将不胜感激!
非常感谢
There are lots of columns (around 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
您可以逆透视成对的列并仅过滤不同的列。
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
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
您必须列出所有列,将它们转换为字符。很多工作,很多 space 的错误,但这是我想到的最好的。