比较2行和2列并找出差异

时间:2019-04-04 14:00:59

标签: sql sql-server

原始数据

+--------+-------+---------------+---------------+---------------+---------------+---------------+---------------+
| RowNum | SeqNo |     Col1      |     Col2      |     Col3      |     Col4      |     Col5      |     Col6      |
+--------+-------+---------------+---------------+---------------+---------------+---------------+---------------+
|      1 | A123  | A             | 'emptystring' | 'emptystring' | 'emptystring' | Z             | 'emptystring' |
|      2 | A123  | 'emptystring' | B             | 'emptystring' | 'emptystring' | 'emptystring' | D             |
|      1 | B123  | 'emptystring' | 'emptystring' | C             | 'emptystring' | 'emptystring' | 'emptystring' |
|      2 | B123  | 'emptystring' | 'emptystring' | 'emptystring' | D             | 'emptystring' | 'emptystring' |
|      1 | C123  | A             | 'emptystring' | B             | 'emptystring' | 'emptystring' | 'emptystring' |
|      2 | C123  | 'emptystring' | A             | 'emptystring' | B             | 'emptystring' | A             |
+--------+-------+---------------+---------------+---------------+---------------+---------------+---------------+

期望结果:

+-------+---------------+----------+
| SeqNo |  From_Value   | To_Value |
+-------+---------------+----------+
| A123  | A             | B        |
| A123  | Z             | D        |
| B123  | C             | D        |
| C123  | 'emptystring' | A        |
+-------+---------------+----------+

如何获得理想的结果?期望的结果是捕获所做的更改(基于期望的结果)。 EmptyString是空白的NOT NULL只是空白。

SeqNo是唯一编号,不会重复(在原始数据中)。

RowNum = 1 = From_Value = Col1,Col3,Col5(不会更改)

RowNum = 2 = To_Value = Col2,Col4,Col6(这些不会更改)

4 个答案:

答案 0 :(得分:0)

要查找这些“更改的值”,可以使用以下查询:

with
from_to as (
  select t1.seqno, t1.col1 as f, t2.col2 as t
  from t t1
  join t t2 on t1.seqno = t2.seqno and t1.rownum = 1 and t2.rownum = 2
  union  
  select t1.seqno, t1.col3 as f, t2.col4 as t
  from t t1
  join t t2 on t1.seqno = t2.seqno and t1.rownum = 1 and t2.rownum = 2
  union
  select t1.seqno, t1.col5 as f, t2.col6 as t
  from t t1
  join t t2 on t1.seqno = t2.seqno and t1.rownum = 1 and t2.rownum = 2
)
select seqno, f as from_value, t as to_value
from from_to
where f is null and t is not null
   or f is not null and t is null
   or f <> t

答案 1 :(得分:0)

create table #Raw (
        RowNum int,
        SeqNo nvarchar(20),
        Col1 nvarchar(max),
        Col2 nvarchar(max),
        Col3 nvarchar(max),
        Col4 nvarchar(max),
        Col5 nvarchar(max),
        Col6 nvarchar(max)
    )
insert #Raw values
    (1, 'A123', 'A', '    ', '    ', '    ', 'Z', '    '),
    (2, 'A123', '    ', 'B', '    ', '    ', '    ', 'D'),
    (1, 'B123', '    ', '    ', 'C', '    ', '    ', '    '),
    (2, 'B123', '    ', '    ', '    ', 'D', '    ', '    '),
    (1, 'C123', 'A', '    ', 'B', '    ', '    ', '    '),
    (2, 'C123', '    ', 'A', '    ', 'B', '    ', 'A')


select  f.SeqNo, f.Col1 [From_Value], t.Col2 [To_Value]
    from #Raw f
    join #Raw t on
        t.SeqNo = f.SeqNo
        and t.RowNum = 2
        and f.Col1 <> t.Col2
    where
        f.RowNum = 1
union
select  f.SeqNo, f.Col3 [From_Value], t.Col4 [To_Value]
    from #Raw f
    join #Raw t on
        t.SeqNo = f.SeqNo
        and t.RowNum = 2
        and f.Col3 <> t.Col4
    where
        f.RowNum = 1
union
select  f.SeqNo, f.Col5 [From_Value], t.Col6 [To_Value]
    from #Raw f
    join #Raw t on
        t.SeqNo = f.SeqNo
        and t.RowNum = 2
        and f.Col5 <> t.Col6
    where
        f.RowNum = 1


drop table #Raw

答案 2 :(得分:0)

这是仅使用一个联接的替代方案。

DECLARE @RowData TABLE(RowNum INT, SeqNo VARCHAR(10), Col1Before VARCHAR(10), Col1After VARCHAR(10), Col2Before VARCHAR(10), Col2After VARCHAR(10), Col3Before VARCHAR(10), Col3After VARCHAR(10))

INSERT INTO @RowData
VALUES
    (1, 'A123', 'A', '', '', '', 'Z', ''),
    (2, 'A123', '', 'B', '', '', '', 'D'),
    (1, 'B123', '', '', 'C', '', '', ''),
    (2, 'B123', '', '', '', 'D', '', ''),
    (1, 'C123', 'A', '', 'B', '', '', ''),
    (2, 'C123', '', 'A', '', 'B', '', 'A')

SELECT
    ColumnChange.SeqNo
    ,ColumnChange.BeforeValue
    ,ColumnChange.AfterValue
FROM
    @RowData AS BeforeRow
    INNER JOIN @RowData AS AfterRow
        ON BeforeRow.SeqNo = AfterRow.SeqNo
            AND BeforeRow.RowNum = 1
            AND AfterRow.RowNum = 2
    CROSS APPLY(
        SELECT
            SeqNo
            ,TableColumn
            ,BeforeValue
            ,AfterValue
        FROM
            (VALUES
                (BeforeRow.SeqNo, 'Col1', BeforeRow.Col1Before, AfterRow.Col1After),
                (BeforeRow.SeqNo, 'Col2', BeforeRow.Col2Before, AfterRow.Col2After),
                (BeforeRow.SeqNo, 'Col3', BeforeRow.Col3Before, AfterRow.Col3After)
            ) AS ColumnChange(SeqNo, TableColumn, BeforeValue, AfterValue)
        WHERE
            ColumnChange.BeforeValue IS NULL AND ColumnChange.AfterValue IS NOT NULL
            OR ColumnChange.BeforeValue IS NOT NULL AND ColumnChange.AfterValue IS NULL
            OR ColumnChange.BeforeValue != ColumnChange.AfterValue
    ) AS ColumnChange

答案 3 :(得分:0)

DECLARE @Raw TABLE(
        RowNum int,
        SeqNo nvarchar(20),
        Col1 nvarchar(max),
        Col2 nvarchar(max),
        Col3 nvarchar(max),
        Col4 nvarchar(max),
        Col5 nvarchar(max),
        Col6 nvarchar(max)
    )

insert @Raw values
    (1, 'A123', 'A', '    ', '    ', '    ', 'Z', '    '),
    (2, 'A123', '    ', 'B', '    ', '    ', '    ', 'D'),
    (1, 'B123', '    ', '    ', 'C', '    ', '    ', '    '),
    (2, 'B123', '    ', '    ', '    ', 'D', '    ', '    '),
    (1, 'C123', 'A', '    ', 'B', '    ', '    ', '    '),
    (2, 'C123', '    ', 'A', '    ', 'B', '    ', 'A')


SELECT SeqNo,value_from,value_to FROM
(
SELECT SeqNo, 1 as _lp, RowNum, Col1 as value_from ,LEAD(Col2,1,Col1) OVER(PARTITION BY SeqNo order by RowNum ) as value_to FROM @Raw
UNION ALL
SELECT SeqNo, 2 as _lp, RowNum, Col3 as value_from ,LEAD(Col4,1,Col3) OVER(PARTITION BY SeqNo order by RowNum ) as value_to FROM @Raw
UNION ALL
SELECT SeqNo, 3 as _lp, RowNum, Col5 as value_from ,LEAD(Col6,1,Col5) OVER(PARTITION BY SeqNo order by RowNum ) as value_to FROM @Raw
) as tab
WHERE value_from!=value_to 
order by SeqNo,_lp