Как получить последовательные строки с учетом условия - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть таблица, которая выглядит следующим образом

    WeekId     PassesCondition
----------------------------------
      1              1
      2              0
      3              0
      4              1
      5              1
      6              1

Мне нужно написать запрос, который отсчитывает последующие недели назад от максимума WeekId, что условие было выполнено.

Я провел некоторый поиск, и мне, кажется, нужно что-то сделать с CTE и ROW_NUMBER(), возможно.Я попробовал несколько вещей, но результаты даже не были достойны того, чтобы публиковать их как «То, что я пробовал до сих пор».

Вывод должен быть просто подсчетом того, сколько недель от Max(WeekId) прошло условие.например, 1, 2, 5 и т. д.

Ответы [ 3 ]

0 голосов
/ 21 декабря 2018

Подсчитать строки, которые находятся между максимумом weekid, который имеет passesCondition = 0 (эксклюзив) и максимумом weekid (эксклюзив):

SELECT COUNT(*)
FROM tablename t
WHERE 
  (t.weekid < (SELECT MAX(weekid) FROM tablename))
  AND
  (t.weekid > (SELECT MAX(weekid) FROM tablename WHERE passesCondition = 0)); 

Если вы хотите включить последний weekid, измените < на <=.

0 голосов
/ 21 декабря 2018

Если вам нужно учесть несколько стартов и остановок, вы можете подсчитать острова, используя запрос, подобный следующему:

DECLARE @T TABLE(WeekId INT, PassedCondition BIT)
INSERT @T VALUES (1,1),(2,0),(3,0),(4,1),(5,1),(6,1),(7,1),(8,0),(9,0),(10,1)

;WITH Holes AS(SELECT WeekID FROM @T WHERE PassedCondition=0),
SegmentStart AS
(
    SELECT WeekId, HoleWeekId 
    FROM
    (
        SELECT  This.WeekId, HoleWeekId = MIN(H.WeekId)
        FROM  @T This
        INNER  JOIN Holes H ON H.WeekId > This.WeekID AND PassedCondition=1
        GROUP BY This.WeekId
        UNION 
        SELECT WeekId = MAX(WeekID), HoleWeekId=MAX(WeekID)+1 
        FROM @T 
        WHERE PassedCondition=1
    )AS X
)
SELECT 
    WeekSegmentEnd = HoleWeekId-1,
    ConsecutiveCount = COUNT(*)
FROM 
    SegmentStart
GROUP BY
    HoleWeekId       
0 голосов
/ 21 декабря 2018

Предполагая, что условие только 0 или 1:

select count(*)
from t
where t.weekid > (select max(t2.weekid) from t t2 where t2.passesCondition = 0) or
      not exists (select 1 from t t2 where t2.passesCondition = 0);

Второе условие не требуется, если вы знаете, что существует строка с passesCondition = 0.

Если вам нравитсяиспользуя оконные функции, вы также можете сделать это с помощью кумулятивного обратного минимума:

select count(*)
from (select t.*,
             min(passesCondition) over (order by weekid desc) as running_min
      from t
     ) t
where running_min = 1;

или not exists можно использовать:

select count(*)
from t
where not exists (select 1
                  from t t2
                  where t2.weekid > t.weekid and t2.passesCondition = 0
                 );

или > all:

select count(*)
from t
where t.weekid > all (select t2.weekid from t t2 where t2.passesCondition = 0);

Я не осознавал, что существует так много разных способов выразить это.Без сомнения, их немало.

...