I have a 2 tables with PARENT-CHILD relationship and their "snapshot" versions:
CREATE TABLE Parent(
ParentId int
)
CREATE TABLE Child(
ChildId int,
ParentId int,
ColA int,
)
CREATE TABLE ParentSnapshot(
ParentSnapshotId int,
ParentId int
)
CREATE TABLE ChildSnaphost(
ChildSnapshotId,
ParentSnapshotId
ChildId int,
ParentId int,
ColA int,
)
At some point, Parent and Child tables are copied to ParentSnapshot and ChildSnaphost:
Now, for given list of ParentSnapshotIds, I need to synchronize ChildSnaphost with their original data (Child table).
How do I write merge statement that for given list ParentSnapshotIds merges ChildTable into ChildSnaphost table:
I'm struggling to write the where condition for list of ParentSnapshotIds, resp ParentIds
You need to join the ParentSnapshot
Parent
and Child
tables in the merge source to get the new list of Child
rows to merge to ChildSnapshot
.
You also need to filter the target ChildSnapshot
by that list of ParentSnapshotId
s. Do NOT do what the other answer has done: an unrestricted merge into ChildSnapshot
, as then all other rows will be deleted, even of snapshots you weren't interested in modifying.
Do NOT place these conditions in the ON
clause. The only thing that goes in the ON
clause is the join condition, no filters should be placed here.
WITH source AS (
SELECT
ps.ParentSnapshotId,
c.ChildId,
ps.ParentId,
c.ColA
FROM
ParentSnapshot ps
INNER JOIN
Child c ON ps.ParentId = c.ParentId
WHERE
ps.ParentSnapshotId IN (1, 500) --assuming you have list of ParentSnapshotId
),
target AS (
SELECT
cs.*
FROM
ChildSnapshot cs
WHERE
cs.ParentSnapshotId IN (1, 500) --assuming you have list of ParentSnapshotId
)
MERGE INTO target AS t
USING source AS s
ON t.ParentSnapshotId = s.ParentSnapshotId AND t.ChildId = s.ChildId
WHEN MATCHED THEN
UPDATE SET
ParentId = s.ParentId,
ColA = s.ColA
WHEN NOT MATCHED BY TARGET THEN
INSERT (ParentSnapshotId, ChildId, ParentId, ColA)
VALUES (s.ParentSnapshotId, s.ChildId, s.ParentId, s.ColA)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;