как обновить row = NULL, если нет совпадений - PullRequest
2 голосов
/ 05 апреля 2019

У меня есть 2 таблицы, подобные этой:

CREATE TABLE #targetTable(id int,date datetime,name varchar(50));
CREATE TABLE #sourceTable(id int,date datetime,name varchar(50));
INSERT INTO #targetTable  values(1,'1905-07-08 00:00:00.000','John');
INSERT INTO #targetTable values(2,'1905-07-08 00:00:00.000','Albrt');
INSERT INTO #targetTable  values(3,'1905-07-08 00:00:00.000','Roy');

INSERT INTO #sourceTable values(1,'1905-07-09 00:00:00.000','jame');

Я хочу обновить таблицу целей, если она не совпадает, то обновить столбец имен цели с NULL.Я хотел бы получить этот результат:

id   date                     name
1   1905-07-09 00:00:00.000    jame
2   1905-07-09 00:00:00.000    null
3   1905-07-09 00:00:00.000    null

мой тестовый запрос не работает: Ошибка: ОБНОВЛЕНИЕ НЕ ДОПУСКАЕТСЯ, КОГДА НЕ СОГЛАСОВАНО.есть ли в любом случае редактировать запрос, чтобы получить результаты?

merge into #targetTable a 
using #sourceTable b on a.id=b.id 
when matched and b.date > a.date then
   update 
   set a.name=b.name,a.date=b.date 
when not matched by Target then 
   update a.date=b.date and a.name = null 

это показывает мне ошибку.Можете ли вы помочь мне, как получить результат?

Ответы [ 5 ]

4 голосов
/ 05 апреля 2019

Без обид, но у вашего запроса много синтаксических проблем.

Во-вторых, оператор слияния не может обновлять значения в целевой таблице, когда они не совпадают. Вы должны попробовать вставить вместо этого.

Вот пример:

MERGE INTO #targetTable a 
USING #sourceTable b 
ON a.id=b.id 
WHEN MATCHED THEN 
    UPDATE SET 
        a.name=b.name,
        a.date=b.date 
WHEN NOT MATCHED BY TARGET THEN 
    INSERT  
    (
        id,
        date,
        name
    )
    VALUES 
    (
        b.id,
        b.date,
        null as name
    )
0 голосов
/ 05 апреля 2019

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

  • UPDATE строка, основанная на id с date и name, но установите name на NULL, когда нет совпадений, и установите date на максимальную дату в в то же время с этим условием.
  • UPDATE с новыми значениями (name, date) при совпадении на id

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

С учетом таблицы и данных это дает:

DECLARE  @targetTable TABLE (id int,date datetime,name varchar(50));
DECLARE  @sourceTable TABLE (id int,date datetime,name varchar(50));
INSERT INTO @targetTable  
VALUES
(1,'1905-07-08 00:00:00.000','John'),
(2,'1905-07-08 00:00:00.000','Albrt'),
(3,'1905-07-08 00:00:00.000','Roy');

INSERT INTO @sourceTable values(1,'1905-07-09 00:00:00.000','jame');

SELECT  id,date,name  FROM @targetTable;
SELECT  id,date,name  FROM @sourceTable;

id  date    name
1   1905-07-08 00:00:00.000 John
2   1905-07-08 00:00:00.000 Albrt
3   1905-07-08 00:00:00.000 Roy

id  date    name
1   1905-07-09 00:00:00.000 jame

То, что вы хотите, в основном совпадает с этим утверждением select:

SELECT 
    t.id,
    CASE 
        WHEN s.id IS NOT NULL THEN s.[date]
        ELSE (SELECT MAX([date]) FROM @sourceTable )
    END AS [date],
    CASE 
        WHEN s.id IS NULL THEN NULL
        ELSE s.name
    END AS [name]
FROM @targetTable AS t
LEFT OUTER JOIN  @sourceTable AS s
    ON t.id = s.id;

ТАК, чтобы сделать это, мы можем включить это в обновление:

UPDATE @targetTable
    SET [date] = CASE 
        WHEN s.id IS NOT NULL THEN s.[date]
        ELSE (SELECT MAX([date]) FROM @sourceTable )
    END,
    [name] = CASE 
        WHEN s.id IS NULL THEN NULL
        ELSE s.name
    END
FROM @targetTable AS t
LEFT OUTER JOIN  @sourceTable AS s
    ON t.id = s.id;

Конечный выход

SELECT id,date,name  FROM @targetTable;

id  date                    name
1   1905-07-09 00:00:00.000 jame
2   1905-07-09 00:00:00.000 NULL
3   1905-07-09 00:00:00.000 NULL
0 голосов
/ 05 апреля 2019

Так что, если я получу вашу проблему, вы просто захотите обновить имя в таблице #targetTable, если в # sourceTable нет подходящей строки.

Вам не нужен оператор MERGE для этого.

UPDATE #targetTable
SET 
    [name] = COALESCE([source].name, NULL)
    , date = [source_date].maxDate
FROM 
    #targetTable AS [target]
    LEFT JOIN #sourceTable AS [source] ON [target].id = [source].id
    CROSS JOIN (SELECT max(date) AS maxDate FROM #sourcetable) AS [source_date] 
WHERE 
    [source].id IS NULL

Это дает следующий вывод:

enter image description here

0 голосов
/ 05 апреля 2019

Вам нужно WHEN NOT MATCHED BY SOURCE, так что-то вроде:

WHEN NOT MATCHED BY SOURCE
THEN UPDATE 
        SET a.name = NULL
0 голосов
/ 05 апреля 2019

Я бы использовал APPLY:

UPDATE t
       SET t.name = s.name, 
           t.date = s.date
FROM #targetTable t OUTER APPLY
     ( SELECT TOP (1) s.*
       FROM #sourceTable s
       WHERE s.id = t.id
     ) s;

Ваше слияние также имеет значение источника:

merge #targetTable a 
using #sourceTable b 
      on a.id=b.id 
when matched  
     then update 
         set a.name = b.name, a.date= b.date 
when not matched by SOURCE  
     then update 
          set a.name = null;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...