最小和最大ID由组和其他条件组成

cla*_*lol 5 sql max min

我在MS SQL Server中有一个类似于下面的表.

      id | Timestamp | active
    -----+-----------+--------
      1  |    1:00   |    1
      1  |    2:00   |    1
      1  |    3:00   |    1
      1  |    4:00   |    0
      1  |    5:00   |    0
      1  |    6:00   |    1
      1  |    7:00   |    0
      1  |    8:00   |    0
      1  |    9:00   |    0
      1  |   10:00   |    1
      1  |   11:00   |    1
      1  |   12:00   |    0
      1  |   13:00   |    1
      2  |    2:00   |    1
      2  |    3:00   |    1
      2  |    4:00   |    0
      2  |    5:00   |    0
      3  |    8:00   |    0
      3  |    9:00   |    0
      4  |    1:00   |    1
      4  |    2:00   |    1
      5  |   16:00   |    0
Run Code Online (Sandbox Code Playgroud)

我想要做的是找出每个ID处于非活动状态(活动= 0)多长时间.我尝试做的是在active = 0时按id分组,并在最小和最大时间进行一次约会.但这会给我一个id 1的结果,表示它已经离线8小时(12:00 - 4:00)@ 12:00.当我真正想要的是一个查询,它将给我以下结果集.

    id | approx. offline in hours |  at time
    ---+--------------------------+-----------
     1 |            1             |    5:00
     1 |            2             |    9:00
     1 |            0             |   12:00
     2 |            1             |    5:00
     3 |            0             |    9:00
     5 |            0             |   16:00
Run Code Online (Sandbox Code Playgroud)

我最初尝试的错误查询是

SELECT id as [Inactive],
       DATEDIFF(hour, MIN(Timestamp), MAX(Timestamp)) as [approx. offline in hours],
       MAX(Timestamp) as [at time]
FROM table
WHERE active = 0
GROUP BY [Inactive]
Run Code Online (Sandbox Code Playgroud)

但该查询的问题在于它会跳过两者之间的活动时间.我一直在看这个问题已被问及使用PARTITION回答,但看起来这个问题已经足够不同了,答案对于我无法理解的问题来说太具体了.

任何帮助表示赞赏.

Gor*_*off 3

解决此问题的一种方法(适用于任何数据库)是使用相关子查询。这个想法是为每个连续的活动值字符串分配一个组名。特定的组名是值的下一次更改的时间。

select id, active, min(TimeStamp), max(TimeStamp)
from (select t.*,
             (select min(timeStamp) from t t2 where t2.id = t.id and t2.timeStamp > t.timeStamp and t2.active <> t.active
             ) groupName
      from t
     ) t
group by id, groupName, active
Run Code Online (Sandbox Code Playgroud)

需要注意的是,如何将时间戳转换为持续时间取决于数据库。由于您没有指定数据库,我将让您添加该逻辑。

另外,如果给定 id 的最后一条记录处于非活动状态,则组名为 NULL。那不是问题。