2016-03-01 2 views
4

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

Пример данных (идентификатор является тождеством):

id  person result 
1  1  0 
2  1  1 
3  1  1 
4  2  1 
5  2  0 
6  1  1 
7  1  0 
8  2  0 
9  2  0 
10  2  0 

С этим я хотел бы рассчитывать на максимальное количество consecutiveresult = 1 для каждого человека. В результате в этом примере будет

person max_count 
1  3 
2  1 

Я попытался с помощью ROW_NUMBER() OVER (PARTITION BY) как этот

SELECT person, 
ROW_NUMBER() OVER (PARTITION BY person, result ORDER BY id) AS max_count  
FROM TABLE 

, но это дает мне accumulative подсчет вместо consecutive одного.

Что делать, чтобы выполнить последовательный подсчет? Любой намек был бы оценен. Заранее спасибо

+1

Подсказка: 'пробелы и острова'. Что такое версия SQL Server? Я думаю, что могу написать окончательный запрос, но одно неясно. Почему 'max_count' для человека' 1' является '2'? На основе вашего образца это должно быть '3', нет? Строки с идентификаторами: '2,3,6'. Строки '4,5' для разных людей, я думаю, их следует игнорировать, не так ли? Или вас интересует строгая последовательная последовательность, где идентификаторы ** должны быть в последовательности без пробелов? Если вы добавите еще несколько строк в образец, которые объяснят разные варианты, это поможет понять, что вам нужно. –

+0

@ Владимир Баранов, вы правы. Я сделал ошибку в вопросе. Сейчас это исправит. – ydoow

ответ

3

Это похоже на классическую проблему gaps-and-islands. Изучите промежуточные результаты каждого CTE в запросе ниже, чтобы понять, что происходит.

Выборочные данные

Я добавил человек 3 с двумя последовательностями положительных результатов, так что мы могли бы найти самую длинную последовательность.

DECLARE @T TABLE (id int, person int, result int); 
INSERT INTO @T (id, person, result) VALUES 
(1 , 1, 0), 
(2 , 1, 1), 
(3 , 1, 1), 
(4 , 2, 1), 
(5 , 2, 0), 
(6 , 1, 1), 
(7 , 1, 0), 
(8 , 2, 0), 
(9 , 2, 0), 
(10, 2, 0), 
(11, 3, 0), 
(12, 3, 1), 
(13, 3, 1), 
(14, 3, 1), 
(15, 3, 1), 
(16, 3, 0), 
(17, 3, 1), 
(18, 3, 1), 
(19, 3, 0), 
(20, 3, 0); 

Запрос

WITH 
CTE_RowNumbers 
AS 
(
    SELECT 
     id, person, result 
     ,ROW_NUMBER() OVER (PARTITION BY person ORDER BY ID) AS rn1 
     ,ROW_NUMBER() OVER (PARTITION BY person, result ORDER BY ID) AS rn2 
    FROM @T 
) 
,CTE_Groups 
AS 
(
    SELECT 
     id, person, result 
     ,rn1-rn2 AS GroupNumber 
    FROM CTE_RowNumbers 
) 
,CTE_GroupSizes 
AS 
(
    SELECT 
     person 
     ,COUNT(*) AS GroupSize 
    FROM CTE_Groups 
    WHERE 
     result = 1 
    GROUP BY 
     person 
     ,GroupNumber 
) 
SELECT 
    person 
    ,MAX(GroupSize) AS max_count 
FROM CTE_GroupSizes 
GROUP BY person 
ORDER BY person; 

Результат

+--------+-----------+ 
| person | max_count | 
+--------+-----------+ 
|  1 |   3 | 
|  2 |   1 | 
|  3 |   4 | 
+--------+-----------+ 
+0

В ваших данных образца человек 1 имеет только 2 последовательных положительных результата, но в вашем запросе результат, говорит 3? – Kim

+0

@Kim, запрос позволяет иметь пробелы в идентификаторах при определении последовательности. Для человека '1' строки с идентификаторами' 2,3,6' образуют последовательность строк с 'result = 1'. –

+0

Я вижу ... не заметил изменения, которые он сделал по этому вопросу. Я все еще смотрел на результат, где P1 = 2. – Kim

0

с помощью Case и SUM мы можем достичь результата выше

DECLARE @T TABLE (id int, person int, result int); 
    INSERT INTO @T (id, person, result) VALUES 
    (1 , 1, 0), 
    (2 , 1, 1), 
    (3 , 1, 1), 
    (4 , 2, 1), 
    (5 , 2, 0), 
    (6 , 1, 1), 
    (7 , 1, 0), 
    (8 , 2, 0), 
    (9 , 2, 0), 
    (10, 2, 0) 
    select 
    person, 
    SUM(CASE WHEN RESULT = 1 then 1 else 0 END) 
    from @T 
    GROUP BY person 
+2

Это не соответствует последовательному требованию. Например, для человека 1, если есть 0 между 1s. Это вернет сумму в 1 с без учета нуля. – ydoow

Смежные вопросы