对 SQL 中的连续时间间隔进行分组
Grouping consecutive time intervals in SQL
我有这样的东西
+------+-----+-----------+---------+
| Room | Day | StartTime | EndTime |
+------+-----+-----------+---------+
| 1 | 1 | 08:00 | 09:00 |
+------+-----+-----------+---------+
| 1 | 1 | 09:00 | 10:00 |
+------+-----+-----------+---------+
| 1 | 1 | 13:00 | 14:00 |
+------+-----+-----------+---------+
| 2 | 2 | 07:00 | 08:00 |
+------+-----+-----------+---------+
我想按房间、日期和时间间隔分组,但只能按连续的时间间隔分组,例如:
+------+-----+-----------+---------+
| Room | Day | StartTime | EndTime |
+------+-----+-----------+---------+
| 1 | 1 | 08:00 | 10:00 |
+------+-----+-----------+---------+
| 1 | 1 | 13:00 | 14:00 |
+------+-----+-----------+---------+
| 2 | 2 | 07:00 | 08:00 |
+------+-----+-----------+---------+
我有这段代码,但我不满意,因为它也对间隙进行分组并抛出以下结果:
SELECT
sd.Cod_Room,
sd.Cod_Day,
MIN(bd.StartTime) as StartTime,
MAX(bd.EndTime) as EndTime
FROM
Schedule.ScheduleDetail AS sd
INNER JOIN Schedule.BlockDetail AS bd ON sd.Cod_BlockDetail = bd.Cod_BlockDetail
GROUP BY
sd.Room, sd.Day
+------+-----+-----------+---------+
| Room | Day | StartTime | EndTime |
+------+-----+-----------+---------+
| 1 | 1 | 08:00 | 14:00 |
+------+-----+-----------+---------+
| 2 | 2 | 07:00 | 08:00 |
+------+-----+-----------+---------+
我正在阅读有关 lead() 和 lag() 的内容,但它花费的时间比我想象的要多。
感谢您的帮助
您可以通过识别重叠的组然后累加此值来定义组来实现此目的。以下假设 SQL Server 2012+:
with t as (
select sd.Cod_Room, sd.Cod_Day, bd.StartTime, bd.EndTime
from Schedule.ScheduleDetail sd INNER JOIN
Schedule.BlockDetail bd
ON sd.Cod_BlockDetail = bd.Cod_BlockDetail
)
select cod_room, cod_day,
min(startTime) as startTime, max(endTime) as endTime
from (select t.*,
sum(IsStart) over (partition by cod_room, cod_day order by StartTime) as grp
from (select t.*,
(case when StartTime = lag(EndTime) over (partition by cod_room, cod_day order by StartTime)
then 0 else 1
end) as IsStart
from t
) t
) t
group by cod_room, cod_day, grp;
我有这样的东西
+------+-----+-----------+---------+
| Room | Day | StartTime | EndTime |
+------+-----+-----------+---------+
| 1 | 1 | 08:00 | 09:00 |
+------+-----+-----------+---------+
| 1 | 1 | 09:00 | 10:00 |
+------+-----+-----------+---------+
| 1 | 1 | 13:00 | 14:00 |
+------+-----+-----------+---------+
| 2 | 2 | 07:00 | 08:00 |
+------+-----+-----------+---------+
我想按房间、日期和时间间隔分组,但只能按连续的时间间隔分组,例如:
+------+-----+-----------+---------+
| Room | Day | StartTime | EndTime |
+------+-----+-----------+---------+
| 1 | 1 | 08:00 | 10:00 |
+------+-----+-----------+---------+
| 1 | 1 | 13:00 | 14:00 |
+------+-----+-----------+---------+
| 2 | 2 | 07:00 | 08:00 |
+------+-----+-----------+---------+
我有这段代码,但我不满意,因为它也对间隙进行分组并抛出以下结果:
SELECT
sd.Cod_Room,
sd.Cod_Day,
MIN(bd.StartTime) as StartTime,
MAX(bd.EndTime) as EndTime
FROM
Schedule.ScheduleDetail AS sd
INNER JOIN Schedule.BlockDetail AS bd ON sd.Cod_BlockDetail = bd.Cod_BlockDetail
GROUP BY
sd.Room, sd.Day
+------+-----+-----------+---------+
| Room | Day | StartTime | EndTime |
+------+-----+-----------+---------+
| 1 | 1 | 08:00 | 14:00 |
+------+-----+-----------+---------+
| 2 | 2 | 07:00 | 08:00 |
+------+-----+-----------+---------+
我正在阅读有关 lead() 和 lag() 的内容,但它花费的时间比我想象的要多。 感谢您的帮助
您可以通过识别重叠的组然后累加此值来定义组来实现此目的。以下假设 SQL Server 2012+:
with t as (
select sd.Cod_Room, sd.Cod_Day, bd.StartTime, bd.EndTime
from Schedule.ScheduleDetail sd INNER JOIN
Schedule.BlockDetail bd
ON sd.Cod_BlockDetail = bd.Cod_BlockDetail
)
select cod_room, cod_day,
min(startTime) as startTime, max(endTime) as endTime
from (select t.*,
sum(IsStart) over (partition by cod_room, cod_day order by StartTime) as grp
from (select t.*,
(case when StartTime = lag(EndTime) over (partition by cod_room, cod_day order by StartTime)
then 0 else 1
end) as IsStart
from t
) t
) t
group by cod_room, cod_day, grp;