Как создать Merge SQL с дублированными данными - PullRequest
2 голосов
/ 10 октября 2019

Как создать MERGE SQL с дублированными данными внутри в Target и Source?

У меня огромный SQL слияния с довольно сложными объединениями, поэтому я создал простой пример для этого вопроса.

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

Source

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

Вот пример, который я сделал, которыйочень простая версия

Как сделать так, чтобы слияние выглядело очень просто?

--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. Теперь объединить

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

Результаты:

Оператор MERGE попытался ОБНОВИТЬ или УДАЛИТЬ одну и ту же строку более одного раза. Это происходит, когда целевая строка соответствует более чем одной исходной строке. Оператор MERGE не может ОБНОВИТЬ / УДАЛИТЬ одну и ту же строку целевой таблицы несколько раз. Уточните предложение ON, чтобы убедиться, что целевая строка совпадает не более чем с одной исходной строкой, или используйте предложение GROUP BY для группировки исходных строк.

1 Ответ

1 голос
/ 10 октября 2019

При обновлении слиянием каждая строка в целевой таблице должна соответствовать только одной строке в исходной таблице. Например, вы можете взять максимальное значение LOAD за 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

Посмотрите, как оно работает на rextester.

...