Идентифицировать и классифицировать разрывы в повторяющихся сериях из 0 и 1 с помощью SQL

#sql #sql-server #tsql

#sql #sql-server #tsql

Вопрос:

Я заинтересован в разбивке PID на упорядоченные фрагменты на основе столбца CID. Пожалуйста, обратите внимание, что OID используется для упорядочения каждой подгруппы PID

GRP должен быть последовательным и начинаться с 0, если первый CID начинается с 0, в то время как GRP должен начинаться с 1, если GRP начинается с 1

 PID         OID         CID         GRP
----------- ----------- ----------- -----------
1           1           0           NULL
1           2           0           NULL
1           3           1           NULL
1           4           1           NULL
1           5           1           NULL
1           6           0           NULL
1           7           0           NULL
2           1           0           NULL
2           2           0           NULL
2           3           1           NULL
2           4           1           NULL
2           5           0           NULL
2           6           1           NULL
2           7           1           NULL
2           8           0           NULL
3           1           1           NULL
3           2           1           NULL
3           3           1           NULL
3           4           1           NULL
3           5           0           NULL
3           6           1           NULL
3           7           1           NULL
3           8           0           NULL
3           9           0           NULL


 

Решение приведенной выше таблицы приведено ниже, я хотел бы решить следующее с помощью T-SQL, однако я даже не уверен, что такая задача может быть возможной. По сути, я пытаюсь определить перерывы в повторении в столбце CID, как только перерыв будет идентифицирован, я хотел бы увеличить показатель GRP

 PID         OID         CID         GRP
----------- ----------- ----------- -----------
1           1           0           0
1           2           0           0
1           3           1           1
1           4           1           1
1           5           1           1
1           6           0           2
1           7           0           2
2           1           0           0
2           2           0           0
2           3           1           1
2           4           1           1
2           5           0           2
2           6           1           3
2           7           1           3
2           8           0           4
3           1           1           1
3           2           1           1
3           3           1           1
3           4           1           1
3           5           0           2
3           6           1           3
3           7           1           3
3           8           0           4
3           9           0           4

 

Вот пример кода для создания приведенной выше таблицы:

 CREATE TABLE ##SOLUTION (PID INT, OID INT,  CID INT, GRP INT)
insert into ##SOLUTION values 
(1,1,0, 0), 
(1,2,0, 0), 
(1,3,1, 1), 
(1,4,1, 1), 
(1,5,1, 1), 
(1,6,0, 2), 
(1,7,0, 2), 

(2,1,0, 0), 
(2,2,0, 0), 
(2,3,1, 1), 
(2,4,1, 1), 
(2,5,0, 2), 
(2,6,1, 3), 
(2,7,1, 3), 
(2,8,0, 4), 

(3,1,1, 1), 
(3,2,1, 1), 
(3,3,1, 1), 
(3,4,1, 1), 
(3,5,0, 2), 
(3,6,1, 3), 
(3,7,1, 3), 
(3,8,0, 4), 
(3,9,0, 4)

 

Заранее благодарю

Ответ №1:

Вы можете использовать lag() для получения предыдущего значения (внутри каждого pid ). Затем условная совокупная сумма создает нужную группировку:

 select s.*,
       sum(case when prev_cid = cid then 0 else 1 end) over (partition by pid order by oid) as grp
from (select s.*,
             lag(cid) over (partition by pid order by oid) as prev_cid
      from solutions s
     ) s
 

Вот скрипка db<> .

Я должен добавить, что SQL Server позволяет очень легко обновлять эти значения с помощью обновляемых CTE:

 with toupdate as (
      select s.*,
             sum(case when prev_cid = cid then 0 else 1 end) over (partition by pid order by oid) as new_grp
      from (select s.*,
                   lag(cid) over (partition by pid order by oid) as prev_cid
            from solution s
           ) s
     )
update toupdate
     set grp = new_grp;