【问题标题】:Min and max by ID over group and other condition组和其他条件下的 ID 最小值和最大值
【发布时间】:2012-12-26 07:04:14
【问题描述】:

我在 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

我想知道每个 ID 何时处于非活动状态(活动 = 0)多长时间。我试图做的是在 active = 0 时按 id 对它进行分组,并在最小和最大时间上做一个 datediff。但这会给我一个 id 1 的结果,表示它在 12:00 时离线 8 小时(12:00 - 4: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

我最初尝试的错误查询是

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]

但该查询的问题在于它跳过了中间的活动时间。我一直在查看使用 PARTITION 提出和回答的THIS 问题,但看起来问题已经足够不同,而且答案对于我无法理解的问题来说太具体了。

感谢任何帮助。

【问题讨论】:

  • 你在使用什么 rdbms? sql-server,oracle?
  • @bluefeet 方括号最有可能 == SQL Server
  • @JoachimIsaksson 我同意,但他们应该说明他们正在使用什么 rdbms。
  • 你说得对,我忘了说我使用的是 SQL Server。我将编辑我的问题并将其包括在内。

标签: sql max min


【解决方案1】:

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

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

需要注意的是,如何将时间戳转换为持续时间取决于数据库。既然你没有指定数据库,我就让你添加那个逻辑。

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

【讨论】:

  • 我认为这个答案有一个错误,因为 ID 更改时 groupName 将为 NULL
  • @Bulat。 . .那不是问题。 NULL 对分组有效,id 包含在group by 列中。
  • 是的,你是对的,这不是问题。您可能只想将 TimesStamp 重命名为 time 以使字段名称保持一致。 sqlfiddle.com/#!3/e5831/45/0
猜你喜欢
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
  • 2017-02-13
  • 2012-02-11
  • 2023-04-02
相关资源
最近更新 更多