【问题标题】:How to get consecutive rows given a condition如何在给定条件下获取连续行
【发布时间】:2018-12-21 15:33:18
【问题描述】:

我有一张像这样的表

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

我需要编写一个查询,从条件已通过的最大值 WeekId 开始计算连续周数。

我已经进行了一些搜索,我似乎需要对CTEROW_NUMBER() 做一些可能的事情。我已经尝试了一些东西,但结果甚至不值得发布为“我到目前为止尝试过的东西”。

输出应该只是从Max(WeekId) 算起多少周条件已通过。例如1、2、5等

【问题讨论】:

  • 输出应该是什么?你试过什么?

标签: sql sql-server common-table-expression


【解决方案1】:

假设条件只有01

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);

我没有意识到有这么多不同的方式来表达这一点。毫无疑问,还有很多。

【讨论】:

  • 这很棒。非常感谢!
【解决方案2】:

如果您需要考虑多个起点和终点,您可以使用类似于以下的查询来计算岛屿数:

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       

【讨论】:

    【解决方案3】:

    计算具有passesCondition = 0(不包括)的最大weekid最大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,请将 &lt; 更改为 &lt;=

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      • 2020-08-09
      • 2018-12-20
      • 1970-01-01
      • 2020-09-20
      • 2013-01-22
      相关资源
      最近更新 更多