Использование CTE вместо курсора - PullRequest
4 голосов
/ 18 июля 2011

У меня есть следующая структура таблицы.

Я просто хочу обновить SubId для всех строк, в которых он равен нулю и где RawLineNumber возрастает на 1, а также SeqNumber возрастает на 1 .

RawlineNumber Claimid SubId SeqNumber
1             6000    A100  1
2             6000    NULL  2
3             6000    NULL  3
10            6000    A200  1
11            6000    NULL  2
25            6000    A300  1
26            6000    NULL  2
27            6000    NULL  3

Я хочу обновить
SubId из RawLineNumber 2 и 3 с A100,
SubId из RawLineNumber 11 с A200,
SubId из RawLineNumber 26 и 27 с A300.

У меня есть курсор, который выполняет эту работу, но могу ли я иметь CTE, чтобы позаботиться об этом?

Ответы [ 3 ]

7 голосов
/ 18 июля 2011
UPDATE  m
SET     subid = q.subid 
FROM    mytable m
CROSS APPLY
        (
        SELECT  TOP 1 subid 
        FROM    mytable mi
        WHERE   mi.rawLineNumber  < m.rawLineNumber 
                AND mi.subid IS NOT NULL
        ORDER BY
                rawLineNumber DESC
        ) q
WHERE   m.subid IS NULL
2 голосов
/ 18 июля 2011

Поскольку было запрошено рекурсивное решение, я решил написать его. Также это работает для пробелов в Seqnumbers и RawlineNumber

declare @t table (RawlineNumber int, Claimid int, SubId varchar(5), SeqNumber int)

insert @t values(1, 6000, 'A100', 1)
insert @t values(2, 6000, NULL, 2)
insert @t values(3, 6000, NULL, 3)
insert @t values(10, 6000, 'A200', 1)
insert @t values(11, 6000, NULL, 2)
insert @t values(25, 6000, 'A300', 1)
insert @t values(26, 6000, NULL, 2)
insert @t values(27, 6000, NULL, 3)

;with cte as
(
select Rawlinenumber, SeqNumber, SubId
from @t where SubId is not null and SeqNumber = 1
union all
select t.Rawlinenumber, t.SeqNumber, c.SubId
from cte c
join
@t t
on c.Rawlinenumber + 1 = t.Rawlinenumber
and c.SeqNumber + 1 = t.SeqNumber
where t.SubId is null and t.SeqNumber > 1
)
update t 
set SubId = c.SubId
from @t t join cte c 
on c.Rawlinenumber = t.Rawlinenumber
where t.SeqNumber > 1

select * from @t
0 голосов
/ 18 июля 2011

Не очень простой SQL-скрипт должен достичь того, что вы хотите:

update my_table t1 set t1.subid = 
  (select t2.subid from my_table t2 
   where t2.rawlinenumber < t1.rawlinenumber
   and t2.seqnumber = 1
   and t2.rawlinenumber = (
                   select max(t3.rawlinenumber)
                   from my_table t3 
                   where t3.seq_number = 1
                   and t3.rawlinenumber <= t2.rawlinenumber)
where t1.subid is null;

Внутренний подвыбор (T3) дает нам последнюю строку с seqnumber = 1 перед текущей строкой, внешний подвыбор дает намSubID для этой строки (использование оконных функций было бы более эффективным, но поскольку вы не упомянули конкретную RDBMS, я придерживаюсь этого :-))

...