#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