Считай до и сгруппируй вместе - PullRequest
1 голос
/ 08 апреля 2019

Я хотел бы, чтобы кто-нибудь дал мне предложение.

Допустим, у меня есть такие данные:

    Ref No      Whatever      Seq      Value
    A           Bla bla…      1        1 
    A           Bla bla…      2        1
    A           Bla bla…      3        0
    A           Bla bla…      4        1
    B           Bla bla…      5        0
    B           Bla bla…      6        1
    B           Bla bla…      7        0
    B           Bla bla…      8        1
    B           Bla bla…      9        0

Как я мог использовать SQL, чтобы получить что-то подобное?

    Ref No      Whatever      Value      Total
    A           Bla bla…      0          2
    B           Bla bla…      0          0
    B           Bla bla…      0          1
    B           Bla bla…      0          1

Обычно пытаются фильтровать на основе значения = 0 и подсчитывать количество записей до этого на основе сортировки Seq.

Спасибо.

Ответы [ 2 ]

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

Вы можете попробовать это:

WITH
    [CTE1] AS
    (
        SELECT [Seq] AS [Val0Seq], [RefNo], [Seq], [Value]
        FROM @Data
        WHERE [Value] = 0
    UNION ALL
        SELECT C.[Val0Seq], D.[RefNo], D.[Seq], D.[Value]
        FROM @Data AS D INNER JOIN [CTE1] AS C ON C.[RefNo] = D.[RefNo] AND C.[Seq] = D.[Seq] + 1
        WHERE D.[Value] <> 0
    ),
    [CTE2] AS
    (
        SELECT MAX([Seq]) AS [Seq], COUNT(*) - 1 AS [Count]
        FROM [CTE1]
        GROUP BY [Val0Seq]
    )
SELECT D.[RefNo], D.[Whatever], D.[Value], C.[Count]
FROM @Data AS D INNER JOIN [CTE2] AS C ON C.[Seq] = D.[Seq]

Первое общее табличное выражение ([CTE1]) является рекурсивным. Я объясню обе части отдельно.

Оператор привязки (SELECT перед UNION ALL) [CTE1] выбирает все записи, имеющие значение 0. Это моя отправная точка. Я назначаю уникальное значение [Val0Seq] этой записи, соответствующее значению [Seq]. Это приведет к следующему:

Val0Seq      Ref No      Seq      Value
3            A           3        0
5            B           5        0
7            B           7        0
9            B           9        0

Рекурсивный оператор (SELECT после UNION ALL) [CTE1] продолжает выделять все записи перед уже найденными записями в CTE, пока их значение не равно 0 и их значения [RefNo] равны. Весь результат CTE1 будет следующим:

Val0Seq      Ref No      Seq      Value
3            A           1        1
3            A           2        1
3            A           3        0
5            B           5        0
7            B           6        1
7            B           7        0
9            B           8        1
9            B           9        0

Второе общее табличное выражение ([CTE2]) группирует данные [CTE1] по [Val0Seq], так как эти группы содержат необходимую мне информацию. Для каждой группы я выбираю наибольшее значение [Seq] (так как это была начальная запись, где значение было 0) и количество записей в группе минус 1 (поскольку я не хочу включать эту начальную запись в результаты подсчета) , Эта логика [CTE2] приводит к следующим данным:

[Seq]      [Count]
3          2
5          0
7          1
9          1

Последний (основной) запрос просто объединяет результаты [CTE2] с исходными данными (в поле [Seq]) и показывает окончательные результаты:

RefNo      Whatever      Value      Count
A          Bla bla...    0          2
B          Bla bla...    0          0
B          Bla bla...    0          1
B          Bla bla...    0          1
0 голосов
/ 08 апреля 2019

Используя условное агрегирование для создания групп записей, я придумал это решение.

Сначала создайте и заполните образец таблицы ( Пожалуйста, сохраните этот шаг в ваших будущих вопросах)

DECLARE @T AS TABLE
(
    RefNo char(1),
    Whatever varchar(10),
    Seq int,
    [Value] int
)


INSERT INTO @T (RefNo, Whatever, Seq, [Value]) VALUES
('A', 'Bla bla…', 1, 1), 
('A', 'Bla bla…', 2, 1),
('A', 'Bla bla…', 3, 0),
('A', 'Bla bla…', 4, 1),
('B', 'Bla bla…', 5, 0),
('B', 'Bla bla…', 6, 1),
('B', 'Bla bla…', 7, 0),
('B', 'Bla bla…', 8, 1),
('B', 'Bla bla…', 9, 0);

Затем общее табличное выражение для создания групп:

WITH CTE AS
(
    SELECT  RefNo, 
            Whatever, 
            Seq, 
            [Value],
            SUM(IIF([Value] = 0, 1, 0)) OVER(ORDER BY Seq) As Grp
    FROM @T
)

Запрос:

SELECT  RefNo, 
        Whatever, 
        [Value], 
        (
            SELECT COUNT(*) 
            FROM CTE AS T1 
            WHERE T1.Grp = T0.Grp -1
            AND T1.[Value] <> 0
            AND T1.RefNo = T0.RefNo
        ) As [Count]
FROM CTE As T0
WHERE [Value] = 0

Результаты:

RefNo   Whatever    Value   Count
A       Bla bla…    0       2
B       Bla bla…    0       0
B       Bla bla…    0       1
B       Bla bla…    0       1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...