Question

I get a file every day that may or may not have changes from the previous day, I copy the file I receive and call it table2, the next day I receive the file I load it in table1 but now I want to see what's changed. The problem is, I don't want to see the entire row, I just want to see what has changed.

CREATE TABLE Table1
([Emp_ID] int, [DOB] date, [code] varchar(10))
;

INSERT INTO Table1
 ([Emp_ID], [DOB], [code])
VALUES
 (55556, '1966-01-15', '5454'),
 (55557, '1980-03-21', '6868'),
 (55558, '1985-04-26', '7979'),
 (55559, '1990-10-17', '1212'),
 (55560, '1992-12-30', '6767')
;
CREATE TABLE Table2
([Emp_ID] int, [DOB] date, [code] varchar(10))
;

INSERT INTO Table2
 ([Emp_ID], [DOB], [code])
VALUES
 (55556, '1966-01-15', '5454'),
 (55557, '1980-03-21', '6868'),
 (55558, '1985-04-26', '7979'),
 (55559, '1990-10-17', '1212'),
 (55560, '1992-12-30', '5555')
;

Now if I use the EXCEPT function I will see

select * from table1
except
select * from table2

EMP_ID  DOB         CODE
55560   1992-12-30  6767

But what If I just want to see the EMP_ID and the field that has changed, so I want to see this result.

EMP_ID  DOB         CODE
55560               6767

Because the Code is all that has changed for that EMP_ID?

Thanks in advance for any suggestions!

Was it helpful?

Solution

You can use a Common Table Expression (CTE) to determine the differences. Then join those results with the initial table, using a CASE expression on each field to determine if the particular field has changed.

;with UpdatedRecords as
( select * from table1
  except
  select * from table2
)
select ur.EMP_ID, 
       CASE WHEN ur.DOB <> t2.DOB THEN ur.DOB ELSE NULL END as DOB,
       CASE WHEN ur.code <> t2.code THEN ur.code ELSE NULL END as code

from UpdatedRecords ur
join table2 t2 on ur.EMP_ID=t2.EMP_ID

OTHER TIPS

try this:

SELECT * FROM [Table1] tb1
WHERE tb1.[EMP_ID] not in (select [EMP_ID] from [Table1])  

It works for me.

But this example is just for ID comparing. Be carefull

EDITED

I just find one article & I hope it will help you to solve your problem:

Example:

(select * from A 
 minus
 select * from B) -- Rows in A that are not in B
 union all
  ( 
   select * from B 
   minus
   select * from A
  ) -- rows in B that are not in A

Also you can see this question

full join probably works better than except in this case; this will cope with deletions and inserts too

 select coalesce(t1.emp_id, t2.emp_id),
 case when isnull(t1.dob,'')<>isnull(t2.dob,'')  then t2.dob else null end  DOB,
 case when isnull(t1.code,'')<>isnull(t2.code,'') then t2.code else null end  Code
 from table1 t1
 full join table2 t2 on t1.emp_id=t2.emp_id
 where isnull(t1.dob,'')<>isnull(t2.dob,'') or isnull(t1.code,'')<>isnull(t2.code,'')

This data massage script will work in your case with sample data. You can tune it. The base idea is to find out what the different columns are.

with u as 
(   
    select emp_id, dob, code  from table1
    union
    select emp_id,  dob, code   from table2
),
d as 
(
    select emp_id, dob, code  from table1
    except
    select emp_id,  dob, code   from table2
),
c as
(
    select u.* from u inner join d
        on u.emp_id = d.emp_id and u.dob = d.dob            
    union
    select u.* from u inner join d
        on u.emp_id = d.emp_id and u.code = d.code
),
w as
(
    select c.emp_id, c.dob, c.code, 'CodeDiff' as Diff 
    from c inner join d
        on c.emp_id = d.emp_id and c.code <> d.code
            and c.dob = d.dob
    union 
    select c.emp_id, c.dob, c.code, 'DobDiff' as Diff 
    from c inner join d
        on c.emp_id = d.emp_id and c.code = d.code
            and c.dob <> d.dob
)
select 
    d.emp_id, 
    case w.Diff 
        when 'DobDiff' then cast(d.dob AS varchar(25))
        else ''
    end as dob,
    case w.Diff 
        when 'CodeDiff' then d.code
        else ''
    end as code
from d inner join w
    on d.emp_id = w.emp_id and d.code <> w.code
        and d.dob = w.dob
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top