Подсчет количества последовательных сгруппированных записей в SQL - PullRequest
0 голосов
/ 14 ноября 2018

Я хотел бы создать и заполнить следующее Нет.записей в поле Curr.Status , показанном ниже с использованием SQL (сервер sql).

ID          Sequence    Prev.Status Curr.Status No. of Entries in Curr.Status
9-9999-9    1           Status D    Status A    1
9-9999-9    2           Status A    Status A    2
9-9999-9    3           Status A    Status A    3
9-9999-9    4           Status A    Status A    4
9-9999-9    5           Status A    Status B    1
9-9999-9    6           Status B    Status B    2
9-9999-9    7           Status B    Status B    3
9-9999-9    8           Status B    Status A    1
9-9999-9    9           Status A    Status A    2
9-9999-9    10          Status A    Status C    1
9-9999-9    11          Status C    Status C    2

Есть ли быстрый способ использования чего-то вроде row_number() - одного этого недостаточно- создать поле, которое я ищу?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Похоже, это проблема групп и островов.Однако существует множество примеров того, как этого добиться:

WITH VTE AS(
        SELECT *
        FROM (VALUES('9-9999-9',1 ,'Status D','Status A'),
                    ('9-9999-9',2 ,'Status A','Status A'),
                    ('9-9999-9',3 ,'Status A','Status A'),
                    ('9-9999-9',4 ,'Status A','Status A'),
                    ('9-9999-9',5 ,'Status A','Status B'),
                    ('9-9999-9',6 ,'Status B','Status B'),
                    ('9-9999-9',7 ,'Status B','Status B'),
                    ('9-9999-9',8 ,'Status B','Status A'),
                    ('9-9999-9',9 ,'Status A','Status A'),
                    ('9-9999-9',10,'Status A','Status C'),
                    ('9-9999-9',11,'Status C','Status C')) V(ID, Sequence, PrevStatus,CurrStatus)),
CTE AS(            
    SELECT ID,
           [Sequence],
           PrevStatus,
           CurrStatus,
           ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [Sequence]) -
           ROW_NUMBER() OVER (PARTITION BY ID,CurrStatus ORDER BY [Sequence]) AS Grp
    FROM VTE V)
SELECT ID,
       [Sequence],
       PrevStatus,
       CurrStatus,
       ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY [Sequence]) AS Entries
FROM CTE;
0 голосов
/ 14 ноября 2018

Вы можете пометить строки, в которых изменяется состояние, используя функцию LAG, и использовать SUM() OVER (), чтобы назначить уникальный номер каждой группе.Нумерация внутри группы тривиальна:

DECLARE @t TABLE (ID VARCHAR(100), Sequence INT, PrevStatus VARCHAR(100), CurrStatus VARCHAR(100));
INSERT INTO @t VALUES
('9-9999-9',  1, 'Status D', 'Status A'),
('9-9999-9',  2, 'Status A', 'Status A'),
('9-9999-9',  3, 'Status A', 'Status A'),
('9-9999-9',  4, 'Status A', 'Status A'),
('9-9999-9',  5, 'Status A', 'Status B'),
('9-9999-9',  6, 'Status B', 'Status B'),
('9-9999-9',  7, 'Status B', 'Status B'),
('9-9999-9',  8, 'Status B', 'Status A'),
('9-9999-9',  9, 'Status A', 'Status A'),
('9-9999-9', 10, 'Status A', 'Status C'),
('9-9999-9', 11, 'Status C', 'Status C');

WITH cte1 AS (
    SELECT *, CASE WHEN LAG(CurrStatus) OVER(ORDER BY Sequence) = CurrStatus THEN 0 ELSE 1 END AS chg
    FROM @t
), cte2 AS (
    SELECT *, SUM(chg) OVER(ORDER BY Sequence) AS grp
    FROM cte1
), cte3 AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY grp ORDER BY Sequence) AS SeqInGroup
    FROM cte2
)
SELECT *
FROM cte3
ORDER BY Sequence

Демонстрация на DB Fiddle

0 голосов
/ 14 ноября 2018

Если Sequence - это столбец идентификаторов, вы можете:

select t.*, 
       row_number() over (partition by (Sequence - seq) order by Sequence) as [No. of Entries in Curr.Status]
from (select t.*, 
             row_number() over (partition by [Curr.Status] order by Sequence) as seq
      from table t
     ) t;

, иначе вам нужно сгенерировать два row_numbers:

select t.*, 
       row_number() over (partition by (seq1- seq2) order by Sequence) as [No. of Entries in Curr.Status]
from (select t.*, 
             row_number() over (partition by id order by Sequence) as seq1
             row_number() over (partition by id, [Curr.Status] order by Sequence) as seq2
      from table t
     ) t;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...