Как обновить несколько строк, используя список, хранящийся в табличных переменных в SQL - PullRequest
0 голосов
/ 26 июня 2018

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

так, например, из этого пошло бы от:

> 1058841   2018-06-20 14:15:04.000 Copy of NtO produced
> 1058841   2018-06-14 19:58:03.000 NTO service date set to 24/05/2018

> 969565    2018-06-20 14:15:01.000 17530   Copy of NtO produced
> 969565    2018-06-14 19:58:03.000 148 NTO service date set to 24/05/2018

к этому:

> 1058841   2018-06-14 19:59:03.000 Copy of NtO produced
> 1058841   2018-06-14 19:58:03.000 NTO service date set to 24/05/2018

> 969565    2018-06-14 19:59:03.000 17530   Copy of NtO produced
> 969565    2018-06-14 19:58:03.000 148 NTO service date set to 24/05/2018

мой код в настоящее время выглядит следующим образом:

declare @thisdate table
(
thisdate datetime,
thisref nvarchar(50)
)

declare @thisdate2 table
(
thisdate2 datetime
)


insert into @thisdate(thisdate) (select te_date from (
select row_number() over (partition by te_system_ref order by (select 0)) as rownumber, te_date from ticket_events where te_system_ref in 
(select sl_system_ref from statutory_letter where sl_letter_batch = 9429)and te_event = 'Copy of NtO produced' and te_system_ref = 969565
) t where rownumber = 1)
;

insert into @thisdate(thisref) select te_system_ref from (
select row_number() over (partition by te_system_ref order by (select 0)) as rownumber, te_system_ref from ticket_events where te_system_ref in 
(select sl_system_ref from statutory_letter where sl_letter_batch = 9429)and te_event = 'Copy of NtO produced' and te_system_ref = 969565
) t where rownumber = 1
;

insert into @thisdate2(thisdate2) select te_date from (
select row_number() over (partition by te_system_ref order by (select 0)) as rownumber, te_date from ticket_events where te_system_ref in 
(select sl_system_ref from statutory_letter where sl_letter_batch = 9429)and te_event like 'NTO service date set to%' and te_system_ref = 969565
) t where rownumber = 1
;


update ticket_events
set te_date = dateadd(minute,1,(select thisdate2 from @thisdate2))
where te_date in (select thisdate from @thisdate) and te_system_ref in (select thisref from @thisdate) and te_event = 'Copy of NtO produced'

Однако проблема в том, что если запрос на выборку, используемый для заполнения переменных, дает более одного результата, он больше не работает. Как бы я решил это?

И быстрый бонусный вопрос, как мне взять последнюю строку вместо первой, используя номера строк?

Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Вы на правильном пути, используя row_number, но ваша реализация немного отклонена.

Чтобы получить приращения в одну минуту от начального te_date, вам нужно как начальное значение te_date, так и инкрементное число для каждой дополнительной строки. Это можно сделать с помощью функции row_number следующим образом:

declare @t table(te_system_ref int,te_date datetime, te_event varchar(100));
insert into @t values
 (1058841,'2018-06-20 14:15:04.000','Copy of NtO produced')
,(1058841,'2018-06-14 19:58:03.000','NTO service date set to 24/05/2018')
,(969565, '2018-06-20 14:15:01.000','17530   Copy of NtO produced')
,(969565, '2018-06-14 19:58:03.000','148 NTO service date set to 24/05/2018')
;

with d as
(
    select te_system_ref
            ,te_date
            ,te_event    -- row_number gets your minute increments
            ,row_number() over (partition by te_system_ref order by te_date) - 1 as rn
    from @t
)
select te_system_ref    -- min() over function gets the earliest date within the te_system_ref group, which we can add the incremental minutes to.
        ,dateadd(minute,rn,min(te_date) over (partition by te_system_ref)) as te_date
        ,te_event
from d
order by te_system_ref
        ,te_date;

Выход:

+---------------+-------------------------+----------------------------------------+
| te_system_ref |         te_date         |                te_event                |
+---------------+-------------------------+----------------------------------------+
|        969565 | 2018-06-14 19:58:03.000 | 148 NTO service date set to 24/05/2018 |
|        969565 | 2018-06-14 19:59:03.000 | 17530   Copy of NtO produced           |
|       1058841 | 2018-06-14 19:58:03.000 | NTO service date set to 24/05/2018     |
|       1058841 | 2018-06-14 19:59:03.000 | Copy of NtO produced                   |
+---------------+-------------------------+----------------------------------------+
0 голосов
/ 26 июня 2018

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

Я не понимаю, почему вы даже используете табличные переменные, все это может быть достигнуто с помощью одного запроса, я думаю?

Моя первая попытка выглядит так:

WITH Updates AS (
    SELECT
        sl.sl_letter_batch, --not really sure how important this is, but it probably needs joining into the final query
        te.te_system_ref,
        MAX(CASE WHEN te.te_event = 'Copy of NtO produced' THEN te_date END) AS original_date,
        MAX(CASE WHEN te.te_event LIKE 'NTO service date set to%' THEN DATEADD(MINUTE, 1, te_date) END) AS new_date
    FROM
        ticket_events te
        INNER JOIN statutory_letter sl ON sl.sl_system_ref = te.te_system_ref
    GROUP BY
        sl.sl_letter_batch,
        te.te_system_ref)
UPDATE
    te
SET
    te_date = new_date
FROM
    ticket_events te
    INNER JOIN Updates u ON u.te_system_ref = te.te_system_ref AND u.original_date = te.te_date
WHERE
    te.te_event = 'Copy of NtO produced';

... но без тестовых данных это просто написание слепого запроса.

...