在 SQL 中,根据匹配的结束时间和开始时间组合顺序事件的最佳方法是什么?
What is the best way in SQL to combine sequential events based on matching end time to start time?
我工作的那个数据库根据零件 ID 和活动时间记录事件。我遇到的问题是这些事件被截断以适合一天之内。如果某个部分的活动时间延续到第二天,则该事件将按其关联的天数拆分。在这种情况下,第二天的活动开始时间戳与前一天的活动结束时间戳相匹配。我正在尝试想出一种方法,将这些拆分事件组合成一个记录,其中 "true" 每个部分处于活动状态时的开始和结束时间。
这是数据集的示例:
date part_id active_start active_end
1/1/2019 100 1/1/19 8:00 1/1/19 9:30
1/1/2019 100 1/1/19 14:00 1/2/19 0:00
1/2/2019 100 1/2/19 0:00 1/3/19 0:00
1/3/2019 100 1/3/19 0:00 1/4/19 0:00
1/4/2019 100 1/4/19 0:00 1/4/19 8:00
1/7/2019 100 1/7/19 6:00 1/8/19 0:00
1/8/2019 100 1/8/19 0:00 1/9/19 0:00
1/9/2019 100 1/9/19 0:00 1/9/19 11:30
1/11/2019 100 1/11/19 12:00 1/11/19 22:00
1/13/2019 100 1/13/19 14:30 1/14/19 0:00
1/14/2019 100 1/14/19 0:00 1/15/19 0:00
1/15/2019 100 1/15/19 0:00 1/15/19 8:30
我正在尝试将其缩减为以下内容:
date part_id active_start active_end
1/1/2019 100 1/1/19 8:00 1/1/19 9:30
1/1/2019 100 1/1/19 14:00 1/4/19 8:00
1/7/2019 100 1/7/19 6:00 1/9/19 11:30
1/11/2019 100 1/11/19 12:00 1/11/19 22:00
1/13/2019 100 1/13/19 14:30 1/15/19 8:30
有大约 70 个不同的部件号,每个部件号在观察期内有多达 200 个不同的活动事件。活动事件最多可以持续几天。由于我在 SQL 方面相当缺乏经验,任何帮助将不胜感激。
这是一个间隙和孤岛问题,您希望将相邻的行组合在一起。
这是一种使用 window 函数的解决方案:
select
min(date) date,
part_id,
min(active_start) active_start,
max(active_end) active_end
from (
select
t.*,
sum(case when lag_active_end = active_start then 0 else 1 end)
over(partition by part_id order by active_start) grp
from (
select
t.*,
lag(active_end) over(partition by part_id order by active_start) lag_active_end
from mytable t
) t
) t
group by part_id, grp
最内层查询检索具有相同 part_id
的前一条记录的结束日期。中间查询执行一个 window 总和,每次前一个结束日期不等于当前开始日期时该总和增加 1:这定义了相邻行的组。最后,外部查询按组聚合,并计算范围的开始和结束。
我工作的那个数据库根据零件 ID 和活动时间记录事件。我遇到的问题是这些事件被截断以适合一天之内。如果某个部分的活动时间延续到第二天,则该事件将按其关联的天数拆分。在这种情况下,第二天的活动开始时间戳与前一天的活动结束时间戳相匹配。我正在尝试想出一种方法,将这些拆分事件组合成一个记录,其中 "true" 每个部分处于活动状态时的开始和结束时间。
这是数据集的示例:
date part_id active_start active_end
1/1/2019 100 1/1/19 8:00 1/1/19 9:30
1/1/2019 100 1/1/19 14:00 1/2/19 0:00
1/2/2019 100 1/2/19 0:00 1/3/19 0:00
1/3/2019 100 1/3/19 0:00 1/4/19 0:00
1/4/2019 100 1/4/19 0:00 1/4/19 8:00
1/7/2019 100 1/7/19 6:00 1/8/19 0:00
1/8/2019 100 1/8/19 0:00 1/9/19 0:00
1/9/2019 100 1/9/19 0:00 1/9/19 11:30
1/11/2019 100 1/11/19 12:00 1/11/19 22:00
1/13/2019 100 1/13/19 14:30 1/14/19 0:00
1/14/2019 100 1/14/19 0:00 1/15/19 0:00
1/15/2019 100 1/15/19 0:00 1/15/19 8:30
我正在尝试将其缩减为以下内容:
date part_id active_start active_end
1/1/2019 100 1/1/19 8:00 1/1/19 9:30
1/1/2019 100 1/1/19 14:00 1/4/19 8:00
1/7/2019 100 1/7/19 6:00 1/9/19 11:30
1/11/2019 100 1/11/19 12:00 1/11/19 22:00
1/13/2019 100 1/13/19 14:30 1/15/19 8:30
有大约 70 个不同的部件号,每个部件号在观察期内有多达 200 个不同的活动事件。活动事件最多可以持续几天。由于我在 SQL 方面相当缺乏经验,任何帮助将不胜感激。
这是一个间隙和孤岛问题,您希望将相邻的行组合在一起。
这是一种使用 window 函数的解决方案:
select
min(date) date,
part_id,
min(active_start) active_start,
max(active_end) active_end
from (
select
t.*,
sum(case when lag_active_end = active_start then 0 else 1 end)
over(partition by part_id order by active_start) grp
from (
select
t.*,
lag(active_end) over(partition by part_id order by active_start) lag_active_end
from mytable t
) t
) t
group by part_id, grp
最内层查询检索具有相同 part_id
的前一条记录的结束日期。中间查询执行一个 window 总和,每次前一个结束日期不等于当前开始日期时该总和增加 1:这定义了相邻行的组。最后,外部查询按组聚合,并计算范围的开始和结束。