如果间隔小于 5 秒,则将多行合并为一行

Posted

技术标签:

【中文标题】如果间隔小于 5 秒,则将多行合并为一行【英文标题】:Merge several rows into one if they have a gap less than a 5 seconds 【发布时间】:2021-03-01 19:59:48 【问题描述】:

我正在尝试找到一个 SQL 查询,它可以让我从一个间隔小于 5 秒的表中将一些行合并为一个行。例如,我有一个如下表:

Name    |    Time
==============================
John       2021-02-01 13:08:10
John       2021-02-01 13:08:12
John       2021-02-01 17:35:23
John       2021-02-07 11:16:31
Walt       2021-01-14 10:23:48
Joseph     2021-01-23 07:04:33
Walt       2021-01-14 10:23:51
Walt       2021-01-04 09:22:45

所以,我想要这样的结果:

Name    |    Time
==============================
John       2021-02-01
John       2021-02-01
John       2021-02-07
Walt       2021-01-14
Walt       2021-01-04
Joseph     2021-01-23

对于 John,有两行之间的间隔小于 5 秒,因此它们将在同一天合并为一行。沃尔特也是如此。

我可以使用 SQL 查询来做到这一点吗?

提前谢谢你。

【问题讨论】:

你试过什么?请向我们展示您的尝试。如果有一大堆记录,每条记录距离上一条记录不到 5 秒,会发生什么?合并它们? 时间组件会发生什么?如果一行中有多行怎么办? @DaleK 如果有很多行,每行小于5s,则应该只有一行与该行的当前日期。 【参考方案1】:

您只需要检查下一个日期是否在当前行之后的 5 秒内,如果是 - 删除这样的行。这可以通过LEAD解析函数来实现。

with a as (
  select 'John'   as name, convert(datetime, '2021-02-01 13:08:10', 120) as dt union all
  select 'John'   as name, convert(datetime, '2021-02-01 13:08:12', 120) as dt union all
  select 'John'   as name, convert(datetime, '2021-02-01 13:08:15', 120) as dt union all
  select 'John'   as name, convert(datetime, '2021-02-01 17:35:23', 120) as dt union all
  select 'John'   as name, convert(datetime, '2021-02-07 11:16:31', 120) as dt union all
  select 'Walt'   as name, convert(datetime, '2021-01-14 10:23:48', 120) as dt union all
  select 'Joseph' as name, convert(datetime, '2021-01-23 07:04:33', 120) as dt union all
  select 'Walt'   as name, convert(datetime, '2021-01-14 10:23:51', 120) as dt union all
  select 'Walt'   as name, convert(datetime, '2021-01-04 09:22:45', 120) as dt
)
, gap_size as (
  select
    name,
    dt,
    /*Check the difference between current row and the next row per name*/
    datediff(s,
      dt,
      lead(dt) over(partition by name order by dt asc)
    ) as within_5_secs_with_next
  from a
)
select
  name,
  cast(dt as date) as dt_date
from gap_size
where coalesce(within_5_secs_with_next, 10) >= 5
order by name, dt asc
GO
姓名 | dt_date :----- | :--------- 约翰 | 2021-02-01 约翰 | 2021-02-01 约翰 | 2021-02-07 约瑟夫 | 2021-01-23 沃尔特 | 2021-01-04 沃尔特 | 2021-01-14

db小提琴here

【讨论】:

这正是我想要的。非常感谢@astentx

以上是关于如果间隔小于 5 秒,则将多行合并为一行的主要内容,如果未能解决你的问题,请参考以下文章

在Oracle中将多行合并为一行? [复制]

sqlserver字符串多行合并为一行

如何快速批量将多行的内容,变成一行?

sqlServer 多行合并为一行

使用不同的时间间隔合并并填充Pandas中的两个数据帧

使用 xsel 将多行合并为一行