Обновление определенных значений столбцов на основе других столбцов в mssql - PullRequest
0 голосов
/ 15 апреля 2019

У меня есть огромная таблица, в которой мне нужно обновить значение в одном столбце на основе значений из 2 других столбцов, я извлекаю данные и помещаю их в другую новую таблицу #temp где формат данных фрагмента выглядит следующим образом

DOC_GUID     NAME   Value   Timestamp 
--------     ----   -----   ---------
1111         V1     AC      1134
1111         V2     AB      1134
1112         V1     N       1234
1112         V2     AB      1234
1113         V1     AC      1334
1113         V2     N       1334
1114         V1     N       1434
1114         V2     N       1434

Мне нужно обновить значения, чтобы они стали такими

DOC_GUID     NAME   Value   Timestamp 
--------     ----   -----   ---------
1111         V1     AC      1134
1111         V2     AC      1134
1112         V1     AB      1234
1112         V2     AB      1234
1113         V1     AC      1334
1113         V2     AC      1334
1114         V1     N       1434
1114         V2     N       1434

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

UPDATE #temp
SET Value = CASE WHEN (A.DOC_GUID = B.DOC_GUID
                      FROM #temp A inner join #temp B
                      ON A.Value= 'AC' OR 
                      B.Value = 'AC')
                 THEN 'AC'
                 WHEN (A.DOC_GUID = B.DOC_GUID
                      FROM #temp A inner join #temp B
                      ON A.Value= 'AB' OR 
                      B.Value = 'AB')
                 THEN 'AB' END

Ответы [ 3 ]

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

DDL:

declare @tbl table (DOC_GUID int, NAME varchar(3), Value varchar(3),  Timestamp int );
insert into @tbl values
(1111,'V1','AC',1134),
(1111,'V2','AB',1134),
(1112,'V1','AB',1234),
(1112,'V2','N',1234),
(1113,'V1','AC',1334),
(1113,'V2','N',1334),
(1114,'V1','N',1434),
(1114,'V2','N',1434);

Запрос на обновление:

update t1 set t1.Value = t2.Value
from @tbl t1 join (
    select *,
           -- here I use case statement to make AC come before AB
           row_number() over (partition by DOC_GUID order by case when [Value] = 'AC' then 'AA' else [Value] end) rn
    from @tbl
) t2 on t1.DOC_GUID = t2.DOC_GUID
where t2.rn = 1
1 голос
/ 15 апреля 2019

Вы можете сделать это, используя оконную функцию и обновляемый CTE:

with toupdate as (
      select t.*,
             max(case when seqnum = 1 then value end) over (partition by doc_guid) as use_value
      from (select t.*,
                   row_number() over (partition by doc_guid order by priority) as seqnum
            from t left join
                 (values ('AC', 1),
                         ('AB', 2),
                         ('N', 3)
                 ) v(value, priority)
                 on v.value = t.value
           ) t
     )
update toupdate
    set value = use_value
    where use_value <> value;

Этот подход имеет два основных преимущества.

Во-первых, изменить приоритеты довольно просто, потому что онивстроено в предложение VALUES().

Во-вторых, внешнее предложение where обновляет только те строки, которые необходимо обновить.

Это также должно иметь хорошие характеристики производительности.

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

Мы можем попробовать использовать CASE вместе с предложением EXISTS:

UPDATE t1
SET Value = CASE WHEN EXISTS (SELECT 1 FROM #temp t2
                              WHERE t1.DOC_GUID = t2.DOC_GUID AND
                                    t2.Value = 'AC')
                 THEN 'AC'
                 WHEN EXISTS (SELECT 1 FROM #temp t2
                              WHERE t1.DOC_GUID = t2.DOC_GUID AND
                                    t2.Value = 'AB')
                 THEN 'AB'
                 ELSE 'N' END
FROM #temp t1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...