¿Cómo crear MERGE SQL con datos duplicados dentro en Target y Source?

Tengo un gran Merge SQL con uniones bastante complicadas, así que creé un ejemplo simple para esta pregunta.

Target
ID  Load
1   1
2   2
3   3
3   3
4   4
5   5

Fuente

ID  Load
1   111
3   333
3   444
6   666


Result should be:

  ID    Load
    1   111
    2   2
    3   444
    3   444
    4   4
    5   5
    6   666

Aquí hay un ejemplo que hice, que es una versión muy simple.

¿Cómo hacer que Merge se vea muy simple?

--1. Create tables

       CREATE TABLE [dbo].[Target](
            [ID] [int] NOT NULL,
            [Load] [INT] NOT NULL
        ) ON [PRIMARY]


        CREATE TABLE [dbo].[Source](
            [ID] [int] NOT NULL,
            [Load] [int] NOT NULL
        ) ON [PRIMARY]

--2. We need to insert data into Target and Source


    --Insert Duplicated Data, where ID: 3 is duplicated
    INSERT INTO dbo.Target (ID, [LOAD]) VALUES (1,1),(2,2),(3,3),(3,3),(4,4),(5,5)

    --We update Load for every match, 
    --We need insert new data as 
    INSERT INTO dbo.Source (ID, [LOAD]) VALUES (1,111),(3,333),(3,444),(6,666)


SELECT * from dbo.Target
SELECT * from dbo.Source

--3. Ahora fusionar

--Expected: 
-- 111 get 111
-- 333 get 444
-- 6 inserted with 666

BEGIN TRANSACTION

MERGE dbo.Target AS T 
USING dbo.Source AS S
ON T.ID = S.ID
WHEN MATCHED THEN
     UPDATE 
        SET T.[Load] = S.[Load] --Update Load to See what is going on
WHEN NOT MATCHED THEN 
    INSERT (ID, [Load])
     VALUES
     (ID,[Load])
    OUTPUT $action,  deleted.*, inserted.*   --INTO #A_Updated
;

ROLLBACK TRANSACTION

--How to make it work, and ignore duplicate data?

Resultados:

La instrucción MERGE intentó ACTUALIZAR o BORRAR la misma fila más de una vez. Esto sucede cuando una fila de destino coincide con más de una fila de origen. Una instrucción MERGE no puede ACTUALIZAR / BORRAR la misma fila de la tabla de destino varias veces. Refine la cláusula ON para asegurarse de que una fila de destino coincida como máximo con una fila de origen, o use la cláusula GROUP BY para agrupar las filas de origen.

2
justromagod 10 oct. 2019 a las 15:45

1 respuesta

La mejor respuesta

Para una actualización de combinación, cada fila de la tabla de destino debe coincidir con una única fila de la tabla de origen. Por ejemplo, podría tomar el valor máximo de LOAD por ID:

MERGE   dbo.Target AS T 
USING   (
        SELECT  ID
        ,       MAX(LOAD) as LOAD
        FROM    dbo.Source
        GROUP BY
                ID
        ) AS S
ON      T.ID = S.ID

Véalo funcionando en rextester.

1
Andomar 10 oct. 2019 a las 12:57