Объединять только ненулевые поля из источника, оставляя другие поля в цели без изменений - PullRequest
0 голосов
/ 04 апреля 2019

Реальные данные имеют больше столбцов. Образец целевой таблицы имеет поле уникального идентификатора. Поля данных имеют существующие данные. Необходимо обновить записи, но обновляются только некоторые поля.

-- Original/target table
DECLARE @target TABLE (
    ID      varchar(4) NOT NULL,
    x        int NULL,
    y        int NULL,
    z        int NULL );

INSERT INTO @target (ID, x, y, z)
VALUES ('A1', NULL, 2, 3),
       ('A2', 1, 2, NULL),
       ('C4', 1, 2, 3),
       ('Z5', 1, 2, 3)
       ;

--- Updates needed:
DECLARE @updates TABLE (
    ID      varchar(4) NOT NULL,
    x        int NULL,
    y        int NULL,
    z        int NULL );

INSERT INTO @updates (ID, x, y, z)
VALUES ('A1', NULL , 101, NULL),
       ('A2', 201, NULL, NULL),
       ('C4', NULL, NULL, 40),
       ('Z5', NULL, NULL, 99999)

Мне нужно, чтобы пользователи отправляли мне обновления данных, которые я буду использовать для обновления / слияния с целевой таблицей. Пользователь может обновить определенные поля, но не другие поля. Поэтому, когда исходная таблица имеет значение, мне нужно обновить соответствующее поле назначения, но оставить остальные поля (которые являются нулевыми в источнике) без изменений. Изменяйте целевое поле, только если оно явно указано (не ноль) в источнике.

Например, исходная запись с ID = A1 имеет обновленное значение для "y", равное 101. После объединения мне нужно, чтобы целевая запись для A1 содержала: NULL, 101, 3

Мне также нужен способ «очистить» запись в цели. Я подумал, что, возможно, можно будет использовать специальное значение для данных, таких как «99999», показанное в записи с идентификатором Z5. Если источником является «99999», тогда установите целевое поле в NULL.

Я не буду добавлять какие-либо записи, только совпадающие с существующими идентификаторами в цели.

UPDATE:

Это решение, объединенное из обоих ответов, похоже, работает:

update t
    set x = coalesce(u.x, t.x),
        y = coalesce(u.y, t.y),
        z = coalesce(u.z, t.z)
from @target t join
     @updates u
     on t.id = u.id;

update t
    set 
    x = NULLIF(ISNULL(u.x,t.x),'99999'),
    y = NULLIF(ISNULL(u.y,t.y),'99999'),
    z = NULLIF(ISNULL(u.z,t.z),'99999')
from @target t join
     @updates u
     on t.id = u.id;

select * from @target

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Звучит так, как вам нужно:

SET Target.Field = NULLIF(ISNULL(Source.Field,Target.Field),'99999')
0 голосов
/ 04 апреля 2019

Я думаю:

update t
    set x = coalesce(u.x, t.x),
        y = coalesce(u.y, t.y),
        z = coalesce(u.z, t.z)
from @target t join
     @updates u
     on t.id = u.id;

Если вы хотите очистить всю запись, я бы рекомендовал добавить дополнительный флаг к @updates:

update t
    set x = (case when u.clear_record = 1 then null
                  when u.x is not null then u.x
                  else t.x
             end),
        y = (case when u.clear_record = 1 then null
                  when u.y is not null then u.y
                  else t.y
             end),
        z = (case when z.clear_record = 1 then null
                  when u.z is not null then u.z
                  else t.z
             end)
from @target t join
     @updates u
     on t.id = u.id;

EDIT:

Вы можете очистить определенные поля, используя специальное значение, используя похожую логику:

update t
    set x = (case when u.clear_record = 1 or u.x = '99999' then null
                  when u.x is not null then u.x
                  else t.x
             end),
        y = (case when u.clear_record = 1 or u.y = '9999'9 then null
                  when u.y is not null then u.y
                  else t.y
             end),
        z = (case when z.clear_record = 1 or u.z = '99999' then null
                  when u.z is not null then u.z
                  else t.z
             end)
from @target t join
     @updates u
     on t.id = u.id;

Однако я бы не стал использовать '99999' для такого специального значения. Если значения являются строками, я бы предложил пустую строку ('') или '<null>' или '{null}'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...