Показывать только поля из таблицы1, отличные от таблицы2 (Sql server 2008)
Я получаю файл каждый день, который может иметь или не иметь изменения по сравнению с предыдущим днем, я копирую файл, который я получаю, и называю его table2, на следующий день я получаю файл, который загружаю его в table1, но теперь я хочу увидеть, что изменилось. Проблема в том, что я не хочу видеть всю строку, я просто хочу увидеть, что изменилось.
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')
;
Теперь, если я использую функцию EXCEPT, я увижу
select * from table1
except
select * from table2
EMP_ID DOB CODE
55560 1992-12-30 6767
Но что, если я просто хочу увидеть EMP_ID и поле, которое изменилось, поэтому я хочу увидеть этот результат.
EMP_ID DOB CODE
55560 6767
Поскольку Код - это все, что изменилось для этого EMP_ID?
Спасибо заранее за любые предложения!
4 ответа
Вы можете использовать Common Table Expression (CTE) для определения различий. Затем объедините эти результаты с исходной таблицей, используя выражение CASE для каждого поля, чтобы определить, изменилось ли конкретное поле.
;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
Попробуй это:
SELECT * FROM [Table1] tb1
WHERE tb1.[EMP_ID] not in (select [EMP_ID] from [Table1])
Меня устраивает.
Но этот пример только для сравнения ID. Будь осторожен
РЕДАКТИРОВАНИЕ
Я просто нахожу одну статью, и я надеюсь, что она поможет вам решить вашу проблему:
Пример:
(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
Также вы можете увидеть этот вопрос
Полное объединение, вероятно, работает лучше, чем в этом случае; это будет справляться с удалениями и вставками тоже
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,'')
Этот сценарий массажа данных будет работать в вашем случае с образцами данных. Вы можете настроить это. Основная идея состоит в том, чтобы выяснить, что представляют собой различные столбцы.
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