Запрос слияния в SQL Server с условным обновлением

#sql #sql-server-2008 #sql-merge

#sql #sql-server-2008 #sql-слияние

Вопрос:

У меня есть таблица с повторяющимися записями. Формат таблицы выглядит следующим образом

Имя таблицы ввода ПЕРВОГО дня -ABC

 ani         cdate
7076419812  2016-10-12 00:00:00.000
9168919394  2016-10-12 00:00:00.000
6282358407  2016-10-12 00:00:00.000
9168834643  2016-10-12 00:00:00.000
 

Я хочу вставить в другую таблицу, которая будет содержать уникальный mdn с TS.Но для даты 2016-10-12 00:00:00.000 я могу легко вставить в другую таблицу, которая имеет тот же формат.

 OUTPUT Table Name-- PQR
MDN,         TS
7076419812  2016-10-12 00:00:00.000
9168919394  2016-10-12 00:00:00.000
6282358407  2016-10-12 00:00:00.000
9168834643  2016-10-12 00:00:00.000
 

но для даты 2016-10-13 00:00:00.000 У меня есть та же запись смешанной даты с тем же MDN, и я хочу обновить существующий MDN новой датой, а оставшийся MDN должен быть вставлен как новые записи.
На второй день записи таблицы ввода имеют вид

 ani         cdate
7076419812  2016-10-13 00:00:00.000
9168919394  2016-10-13 00:00:00.000
6282358233  2016-10-12 00:00:00.000
9168834609  2016-10-12 00:00:00.000
 

результат должен быть таким после обработки таблицы ввода второго дня

    mdn          ts
   7076419812   2016-10-13 00:00:00.000  
    9168919394  2016-10-13 00:00:00.000
    6282358407  2016-10-12 00:00:00.000
    9168834643  2016-10-12 00:00:00.000
    6282358233  2016-10-12 00:00:00.000
    9168834609  2016-10-12 00:00:00.000
 

Это мой запрос:—

 merge PQR as lc
using (select ani, calldate from ABC  ) as st
on lc.mdn = st.ani 
WHEN MATCHED  and lc.ts < st.calldate   THEN 
update set lc.ts = st.calldate
WHEN NOT MATCHED THEN  
insert (mdn,ts) values (st.ani, st.calldate);
 

Комментарии:

1. и в чем же проблема?

2. он не работает. можно увидеть итоговую выходную таблицу

3. извините, может быть, это формат, но я не могу видеть, каков текущий вывод и каков желаемый результат.

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

5. Это WHEN MATCHED and lc.ts < st.calldate кажется довольно хитрым. Разве что-то вроде WHEN MATCHED and dateadd(day,1,cast(lc.ts as date)) = cast(st.calldate as date) этого не было бы безопаснее?

Ответ №1:

Это было слишком долго для комментария, но публикую это для других.

Ваш запрос выглядит нормально, вам нужно уточнить, что для вас возвращается неправильно. Вот некоторые тестовые данные, использующие ту же вашу логику…

 if object_id ('tempdb..#PRQ') is not null drop table #PRQ
create table #PRQ (mdn bigint, ts datetime)

insert into #PRQ (mdn, ts)
values
(7076419812,'2016-10-12 00:00:00.000'),
(9168919394,'2016-10-12 00:00:00.000'),
(6282358407,'2016-10-12 00:00:00.000'),
(9168834643,'2016-10-12 00:00:00.000')



if object_id ('tempdb..#ABC') is not null drop table #ABC
create table #ABC (ani bigint, cdate datetime)

--this is simulating "day 2" where the date is changing for 7076419812 and 9168919394

insert into #ABC (ani, cdate)
values
(7076419812,'2016-10-13 00:00:00.000'),  --date change
(9168919394,'2016-10-13 00:00:00.000'),  --date change
(6282358407,'2016-10-12 00:00:00.000'),
(9168834643,'2016-10-12 00:00:00.000')

--run the merge with the same logic you used

MERGE #PRQ AS T
USING(SELECT ani, cdate FROM #ABC) AS S
ON T.mdn = s.ani
WHEN MATCHED AND t.ts < s.cdate THEN
UPDATE SET t.ts = s.cdate
WHEN NOT MATCHED THEN
INSERT (mdn,ts) VALUES (s.ani, s.cdate);

--you will see the dates changed for 7076419812 and 9168919394
SELECT * FROM #PRQ

--Now we will update it for "day 3"

update #ABC
set cdate = '2016-10-14 00:00:00.000'
where ani in (7076419812,9168919394)

--run the same merge and select the results from #PRQ

MERGE #PRQ AS T
USING(SELECT ani, cdate FROM #ABC) AS S
ON T.mdn = s.ani
WHEN MATCHED AND t.ts < s.cdate THEN
UPDATE SET t.ts = s.cdate
WHEN NOT MATCHED THEN
INSERT (mdn,ts) VALUES (s.ani, s.cdate);

--see the date changes for 7076419812 and 9168919394
SELECT * FROM #PRQ

--now add two new records with two new ani to your ABC table

insert into #ABC (ani, cdate)
VALUES
(5469358407,'2016-10-15 00:00:00.000'),
(1234834643,'2016-10-15 00:00:00.000')

--and now run the merge again, and see the added rows since they won't match

MERGE #PRQ AS T
USING(SELECT ani, cdate FROM #ABC) AS S
ON T.mdn = s.ani
WHEN MATCHED AND t.ts < s.cdate THEN
UPDATE SET t.ts = s.cdate
WHEN NOT MATCHED THEN
INSERT (mdn,ts) VALUES (s.ani, s.cdate);

SELECT * FROM #PRQ
 

Комментарии:

1. я хочу, чтобы это было сделано одним выстрелом .. вы делаете вручную. там может быть тысяча MDN.

2. слияние произойдет «одним выстрелом». Я вручную обновляю временную таблицу в качестве примера… но если ABC была фактической таблицей, которая обновляется с помощью какого-либо приложения, триггера и т. Д., Тогда, когда вы когда-либо запускали задание, которое выполняло слияние, оно обновляло вашу целевую таблицу PRQ.

3. Не могли бы вы уточнить @Ramdeoangh

4. но это условие работает плохо. иногда я получаю повторяющиеся записи или иногда исключение слияния «Оператор СЛИЯНИЯ пытался ОБНОВИТЬ или УДАЛИТЬ одну и ту же строку более одного раза».

5. А. В вашем ABC должно быть более 1 записи для определенного ani. Измените использование на это… ИСПОЛЬЗУЯ (ВЫБЕРИТЕ ani, MAX(cdate) как cdate ИЗ ГРУППЫ #ABC ОТ ani) @Ramdeoangh