У меня есть две таблицы для слияния, одна источник, а другая цель. Данные в Источник являются выходными данными из КТР.
Я пытаюсь вставить данные в Target, но у меня есть два условия для вставки данных в целевую таблицу.
Я использую Merge для обновления существующих данных и вставки новой строки. Целевая таблица включает исторические данные.
Статус в Источнике будет либо 1, либо 2, а статус в Цели будет либо R, либо S.
Вот пример процесса, который мне нужно выполнить.
Ниже приведены данные в исходной и целевой таблицах, а также несколько условий, которые мне нужно проверить.
Источник
| ID |Name | Cond| Status |
+-------+-----+-----+--------+
| 1 | A | XYZ | 1 |
Цель
| ID |Name | Cond| Status | cdate
+-------+-----+-----+--------+
| 1 | A | XYZ | R | 4/09/2019 4:34:28
Условие 1: теперь. Если в исходных данных есть какие-либо изменения, тогда source.status=2 и если target.id=source.id и target.status='R', то цель необходимо обновить с помощью исходных данных.
Источник
| ID |Name | Cond| Status |
+-------+-----+-----+--------+
| 1 | B | MNO | 2 |
Цель
| ID |Name | Cond| Status | cdate
+-------+-----+-----+--------+
| 1 | B | MNO | R | 4/09/2019 4:34:28
Условие 2: после выполнения одной хранимой процедуры target.status
меняется на «S».
Теперь, если target.status = 'S'
и source.status = 2
и (target.name != source.name or target.cond != source.cond)
, необходимо вставить новую строку в цель с target.status
как «R».
Источник
| ID |Name | Cond| Status |
+-------+-----+-----+--------+
| 1 | B | MNO | 2 |
Цель
| ID |Name | Cond| Status |
+-------+-----+-----+--------+
| 1 | A | XYZ | S | 4/09/2019 4:34:28
| 1 | B | MNO | R | 6/09/2019 7:34:28
Для достижения результата я использовал MERGE
, как показано ниже:
MERGE table_1 AS TARGET
USING data_from_cte AS SOURCE ON (TARGET.ID = SOURCE.ID AND Target.status = 'R')
--WHEN RECORDS ARE MATCHED, UPDATE THE RECORDS IF THERE IS ANY CHANGE
WHEN MATCHED AND TARGET.STATUS = 'R'
THEN UPDATE
SET TARGET.name = SOURCE.name,
TARGET.cond = SOURCE.cond,
--WHEN NO RECORDS ARE MATCHED, INSERT THE INCOMING RECORDS FROM SOURCE TABLE TO TARGET TABLE
WHEN MATCHED AND TARGET.STATUS = 'S' AND source.status = 2
AND (target.name != source.name OR target.cond != source.cond)
THEN INSERT (id, name, cond, status)
VALUES (SOURCE.ID, SOURCE.name, SOURCE.cond, 'R')
WHEN NOT MATCHED BY TARGET
THEN INSERT (id, name, cond, status)
VALUES (SOURCE.ID, SOURCE.name, SOURCE.cond, 'R');
Проблема здесь в том, что я не могу сравнить целевой столбец и исходный столбец в WHEN MATCHED
условии MERGE
оператора.
Как я могу решить эту проблему, используя оператор MERGE
или оператор IF ... ELSE
?
Целевая таблица имеет столбец created_date и идентификатор, created_date в сочетании составляют первичный ключ. Также, если в статусе Target есть R, то строку следует обновить, а если есть S, то ее нужно вставить. Я много пробовал, но я потерпел неудачу. Не могли бы вы помочь?
Вы кажетесь довольно близко, там. Вы немного запутались, потому что вам нужно было проверить существование строки S с помощью exists
, и вы пытались сделать это с помощью синтаксиса слияния. Этого делать нельзя: можно только INSERT
на WHEN NOT MATCHED BY TARGET
. Попробуй это:
;MERGE table_1 AS TARGET
USING data_from_cte AS SOURCE -- (add WHERE source.status = 2 to your CTE)
ON (TARGET.ID = SOURCE.ID AND Target.status = 'R')
--WHEN RECORDS ARE MATCHED, UPDATE THE RECORDS IF THERE IS ANY CHANGE
WHEN MATCHED AND TARGET.STATUS = 'R' AND operation='update'
THEN UPDATE
SET TARGET.name = SOURCE.name,
TARGET.cond = SOURCE.cond,
--WHEN NO RECORDS ARE MATCHED AND NO SAME S ROW EXISTS, INSERT THE INCOMING RECORDS FROM SOURCE TABLE TO TARGET TABLE
WHEN NOT MATCHED AND not exists(select 1 from table_1 t1 where t1.ID = SOURCE.ID AND t1.status = 'S' and t1.name = source.name and t1.cond = source.cond)
THEN INSERT (id, name, cond, status)
VALUES (SOURCE.ID, SOURCE.name, SOURCE.cond, 'R')
Второе (WHEN NOT MATCHED
...) условие изменено, но также не забудьте добавить пункт WHERE source.status = 2
в CTE.
Я получил ошибку, используя эту логику, поскольку идентификатор «TARGET.ID» не может быть связан. В предложении WHEN NOT MATCHED оператора MERGE разрешены только исходные столбцы и столбцы в области действия предложения.
Я сделал это на бегу, надо было убрать префикс target.
, так как это самостоятельный вызов table1
. Я изменил код, попробуйте еще раз.
У нас здесь серьезная проблема: какой ключ у
target
? Изначально можно подумать, что этоID
- но вы показываете случай, когда в целевой таблице есть две строки с идентификатором 1. Так скажите мне следующее: если у цели есть и S, и R для одного и того же идентификатора, должен ли он все еще вставлять еще одну строку с R ? Если да, мы можем найти способ, но это приведет к тому, что во время выполнения запроса будет вставляться все больше и больше R-строк. Если нет, то я сомневаюсь, что это можно сделать с помощью слияния, так как вам нужно читать несколько целевых строк, чтобы вывести одну результирующую строку - нужны подзапросы