Альтернативы использованию курсора для обновления базы данных на основе подзапроса - PullRequest
0 голосов
/ 24 апреля 2019

Может быть, этот титул не очень поучителен, но я не могу прийти с менее надуманным. Вот моя проблема:

Я работаю с таблицей, данные которой выглядят как

id  cId        ver      active
1   100         1       0    
2   100         2       1    
3   100         3       1    
4   200         1       0    
5   200         2       1    
6   300         1       1

Для этой таблицы Id - это PK, а cId идентифицирует клиента. в основном мы храним историю версий.

Проблема, которую я пытаюсь решить, состоит в том, чтобы обновить базу данных, установив active = 1 только для самой последней версии, которая является самой высокой [ver] для каждого клиента. (клиент с cId 100 прослушивается в примере)

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

select t.id, t.cId,t.version 
from (select *
      from comp.Clients  a
      where a.ver = (select max(b.ver) from comp.Clients b where a.cId=b.cIdentifier)
    ) t

С этого момента мое решение состоит в том, чтобы подключить этот запрос к курсору, и для каждой записи в курсоре я бы обновил таблицу до active = 0 и active = 1 для текущей записи.

Дело в том, что курсоры - это то, что они есть, есть ли что-то, что дает мне приличную производительность здесь? Я не очень хорошо разбираюсь в CTE, поэтому я не смог придумать решение, которое вращается вокруг этого. Фактическая таблица содержит около 10 тыс. Записей и около 50 полей.

Ответы [ 3 ]

1 голос
/ 24 апреля 2019

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

select cId,Max(ver) as MaxVer into #tmpTable from comp.Clients  group by cid

update c
set active = case when t.cId is not null then 1 else 0 end
from comp.Clients c left join #tmpTable t on t.CId=c.CId and t.MaxVer=c.ver
0 голосов
/ 24 апреля 2019

Используйте обновляемый CTE:

with toupdate as (
      select c.*,
             max(ver) over (partition by CId) as max_ver
      from comp.Clients c
     )
update toupdate
    set active = (case when max_ver = ver then 1 else 0 end);

Вы можете добавить предложение where, чтобы ограничить количество обновляемых строк, если вам нравится:

   where active <> (case when max_ver = ver then 1 else 0 end)
0 голосов
/ 24 апреля 2019

Вместо курсора используйте 2 обновления.Один для обновления значений до 0, а другой для установки последней версии для идентификатора клиента равным 1. Этого должно быть достаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...