显示WHERE子句中找到的正确条件

时间:2012-06-06 17:59:41

标签: tsql

我有两个具有相同列的表。如果发生更改,则会将其记录在table2中,然后我将table1table2进行比较,看看它们是否不同。如果它们不同,我总结说有一个改变,我想在我的结果表中显示它。

例如:

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_changedold_valuenew_value显示相关值。

有什么想法吗?

5 个答案:

答案 0 :(得分:2)

Age,name,profession是否构成主键(或至少是唯一的键?):

如果是这样,你可以这样做:

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 
.......

答案 1 :(得分: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

答案 2 :(得分:1)

经过进一步的脑力激荡后,我得出结论,甘露解决方案可以通过轻微的改进更好地工作。改进是while循环和count变量。如果有多个列同时更改而不只是一个,我们需要这样做。但是,它会导致输出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

答案 3 :(得分: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
    …
  )

答案 4 :(得分:0)

我使用名称列在您的查询中添加了加入@ T2 t2 on t2.name = t1.name 。假设它可用于链接两个表之间的记录。

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)