3

同じ列を持つ2つのテーブルがあります。変更が発生した場合、それはに記録されており、それらが異なるかどうかtable2を比較table1して確認します。table2それらが異なる場合は、変更があったと結論付け、結果のテーブルにそれを表示したいと思います。

例えば:

SELECT t1.name, t1.age, t1.profession, column_changed, old_value, new_value
FROM   table1 t1, table2 t2
WHERE  t1.column1<>t2.column1 
    OR t1.column2<>t2.column2 
    OR t1.column3<>t2.column3

もちろん、このクエリは正しくありません。、、関連する値を表示したいのcolumn_changedですが。old_valuenew_value

何か案は?

4

5 に答える 5

2

年齢、名前、職業は主キー(または少なくとも一意のキー)を形成しますか?

もしそうなら、あなたは次のようなことをすることができます:

SELECT 
  t1.name, t1.age, t1.profession, 
  t1.column1 as t1column1, t2.column1 as t2column1, 
  t1.column2 as t1column2, t2.column2 as t2column2, 
FROM   
  table1 t1, table2 t2 
WHERE 
  (t1.name = t2.name and t1.age = t2.age and t1.profession = t2.profession) and
  (
   t1.column1<>t2.column1      
   OR t1.column2<>t2.column2     
   OR t1.column3<>t2.column3) 

もちろん、これには両方のテーブルで同じである一意のキーが必要です。また、クエリの結果を明確に変更して、変更された列だけでなくすべての列を表示するようにしました。単一のT-SQLクエリでそのように変更されたものを特定するのは厄介です(ただし可能です)ので、このように返すことをお勧めします。ユースケースに応じて、アプリケーション/プレゼンテーション層に変更された列を見つけるか、スキャンするだけです。目でそれ。

本当にT-SQLでそれを実行したい場合は、次のようにUNIONSで実行できます。

SELECT 
  t1.name, t1.age, t1.profession, 
  'column1' as ColumnChanged,
  t1.column1 as oldValue,
  t2.column1 as newValue
FROM   
  table1 t1, table2 t2 
WHERE 
  (t1.name = t2.name and t1.age = t2.age and t1.profession = t2.profession) and
   t1.column1<>t2.column1  
UNION ALL #better peformance than UNION, which would enforce uniqueness
SELECT 
  t1.name, t1.age, t1.profession, 
  'column2' as ColumnChanged,
  t1.column2 as oldValue,
  t2.column2 as newValue
FROM   
  table1 t1, table2 t2 
WHERE 
  (t1.name = t2.name and t1.age = t2.age and t1.profession = t2.profession) and
   t1.column2<>t2.column2 
.......
于 2012-06-06T18:26:11.903 に答える
1

これを試して:

Select t1.name, t1.age, t1.profession,
    case when t1.column1 <> t2.column1 then 'column1 changed'
        when t1.column2 <> t2.column2 then 'column2 changed'
        -- and so on...
        end as [column_changed],
    case when t1.column1 <> t2.column1 then t1.column1
        when t1.column2 <> t2.column2 then t1.column2
        -- and so on...
        end as [old_value],
    case when t1.column1 <> t2.column1 then t2.column1
        when t1.column2 <> t2.column2 then t2.column2
        -- and so on...
        end as [new_value]
From table1 t1, table2 t2
Where t1.column1 <> t2.column1
Or t1.column2 <> t2.column2
Or t1.column3 <> t2.column3
于 2012-06-06T18:07:54.303 に答える
1

これをさらにブレインストーミングした後、私はガンダーソリューションがわずかな改善でより良く機能すると結論付けました。改善点は、whileループとカウント変数です。1つだけではなく、一度に複数の列が変更される場合に備えて、これを用意する必要があります。ただし、NULLも出力されるため、削除するだけで済みます。変更されたクエリは次のとおりです。

WHILE @count<3
BEGIN
  Select t1.name, t1.age, t1.profession,     
    case when t1.column1 <> t2.column1 and @count = 1 then 'column1 changed'         
      when t1.column2 <> t2.column2 @count = 2 then 'column2 changed'         
      -- and so on...         
    end as [column_changed],     
    case when t1.column1 <> t2.column1 @count = 1 then t1.column1         
      when t1.column2 <> t2.column2 @count = 2 then t1.column2         
      -- and so on...         
    end as [old_value],     
    case when t1.column1 <> t2.column1 @count = 1 then t2.column1         
      when t1.column2 <> t2.column2 @count = 2 then t2.column2         
      -- and so on...         
    end as [new_value] 
  From table1 t1, table2 t2 
  Where t1.column1 <> t2.column1 Or t1.column2 <> t2.column2 Or t1.column3 <> t2.column3 
  SET @counter = @counter + 1
END
于 2012-06-07T17:45:20.957 に答える
1

これが単一のSELECTステートメントとして書き直されたソリューションです(または、必要に応じて、@ gandersが同じ行の複数の変更をサポートするように書き直されました):

SELECT
  x.column_changed,
  t1.column1 AS old_value,
  t2.column1 AS new_value
FROM table1 t1
  INNER JOIN table2 t2 ON t1.name = t2.name
  INNER JOIN (
    SELECT 'column1' UNION ALL
    SELECT 'column2' UNION ALL
    …
  ) x (column_changed) ON (
    x.column_changed = 'column1' AND t1.column1 <> t2.column1 OR
    x.column_changed = 'column2' AND t1.column2 <> t2.column2 OR
    …
  )
于 2012-06-09T21:10:41.123 に答える
0

name列を使用して、t2.name=t1.nameの結合@T2t2をクエリに追加しました。2つのテーブル間のレコードをリンクするために使用できると仮定します。

select 
    t1.name, t1.age, t1.profession,
    column_change =
        case when t1.column1 <> t2.column1 then 'column1'
             when t1.column2 <> t2.column2 then 'column2'
             when t1.column3 <> t2.column3 then 'column3'
      end,
   old_value =
        case when t1.column1 <> t2.column1 then t1.column1
             when t1.column2 <> t2.column2 then t1.column2
             when t1.column3 <> t2.column3 then t1.column3
      end,
    new_value = 
        case when t1.column1 <> t2.column1 then t2.column1
             when t1.column2 <> t2.column2 then t2.column2
             when t1.column3 <> t2.column3 then t2.column3
        end
from @T1 t1
    join @T2 t2 on t2.name = t1.name
where 
    (t1.column1 <> t2.column1
    or t1.column2 <> t2.column2
    or t1.column3 <> t2.column3)
于 2012-06-06T18:26:54.867 に答える