如何合并 MySQL 中重叠的日期范围?
How to combine overlapping date ranges in MySQL?
我有一个 table“lessons_holidays”。它可以包含多个假期日期范围,即
"holiday_begin" "holiday_end"
2016-06-15 2016-06-15
2016-06-12 2016-06-16
2016-06-15 2016-06-19
2016-06-29 2016-06-29
如果日期范围重叠,我想合并每个条目。我需要这样的输出:
"holiday_begin" "holiday_end"
2016-06-12 2016-06-19
2016-06-29 2016-06-29
SQL:以下 sql 语句加载所有行。现在我卡住了。
SELECT lh1.holiday_begin, lh1.holiday_end
FROM local_lessons_holidays lh1
WHERE lh1.holiday_impact = '1' AND
(DATE_FORMAT(lh1.holiday_begin, '%Y-%m') <= '2016-06' AND DATE_FORMAT(lh1.holiday_end, '%Y-%m') >= '2016-06') AND
lh1.uid = '1'
这是一个难题,因为您正在使用 MySQL 而变得更难。这是一个想法。查找每组中所有假期的开始日期。然后 "beginning" 标志的累积和处理这些组。剩下的只是聚合。
假设您没有重复的记录,下面应该做您想要的:
select min(holiday_begin) as holiday_begin, max(holiday_end) as holiday_end
from (select lh.*, (@grp := @grp + group_flag) as grp
from (select lh.*,
(case when not exists (select 1
from lessons_holidays lh2
where lh2.holiday_begin <= lh.holiday_end and
lh2.holiday_end > lh.holiday_begin and
(lh2.holiday_begin <> lh.holiday_begin or
lh2.holiday_end < lh.holiday_end)
)
then 1 else 0
end) as group_flag
from lessons_holidays lh
) lh cross join
(select @grp := 0) params
order by holiday_begin, holiday_end
) lh
group by grp;
如果有重复项,只需在对 table 的最内层引用上使用 select distinct
。
Here 是一个 SQL Fiddle.
编辑:
这个版本似乎工作得更好:
select min(holiday_begin) as holiday_begin, max(holiday_end) as holiday_end
from (select lh.*, (@grp := @grp + group_flag) as grp
from (select lh.*,
(case when not exists (select 1
from lessons_holidays lh2
where lh2.holiday_begin <= lh.holiday_begin and
lh2.holiday_end > lh.holiday_begin and
lh2.holiday_begin <> lh.holiday_begin and
lh2.holiday_end <> lh.holiday_end
)
then 1 else 0
end) as group_flag
from lessons_holidays lh
) lh cross join
(select @grp := 0) params
order by holiday_begin, holiday_end
) lh
group by grp;
如图here.
我有一个 table“lessons_holidays”。它可以包含多个假期日期范围,即
"holiday_begin" "holiday_end"
2016-06-15 2016-06-15
2016-06-12 2016-06-16
2016-06-15 2016-06-19
2016-06-29 2016-06-29
如果日期范围重叠,我想合并每个条目。我需要这样的输出:
"holiday_begin" "holiday_end"
2016-06-12 2016-06-19
2016-06-29 2016-06-29
SQL:以下 sql 语句加载所有行。现在我卡住了。
SELECT lh1.holiday_begin, lh1.holiday_end
FROM local_lessons_holidays lh1
WHERE lh1.holiday_impact = '1' AND
(DATE_FORMAT(lh1.holiday_begin, '%Y-%m') <= '2016-06' AND DATE_FORMAT(lh1.holiday_end, '%Y-%m') >= '2016-06') AND
lh1.uid = '1'
这是一个难题,因为您正在使用 MySQL 而变得更难。这是一个想法。查找每组中所有假期的开始日期。然后 "beginning" 标志的累积和处理这些组。剩下的只是聚合。
假设您没有重复的记录,下面应该做您想要的:
select min(holiday_begin) as holiday_begin, max(holiday_end) as holiday_end
from (select lh.*, (@grp := @grp + group_flag) as grp
from (select lh.*,
(case when not exists (select 1
from lessons_holidays lh2
where lh2.holiday_begin <= lh.holiday_end and
lh2.holiday_end > lh.holiday_begin and
(lh2.holiday_begin <> lh.holiday_begin or
lh2.holiday_end < lh.holiday_end)
)
then 1 else 0
end) as group_flag
from lessons_holidays lh
) lh cross join
(select @grp := 0) params
order by holiday_begin, holiday_end
) lh
group by grp;
如果有重复项,只需在对 table 的最内层引用上使用 select distinct
。
Here 是一个 SQL Fiddle.
编辑:
这个版本似乎工作得更好:
select min(holiday_begin) as holiday_begin, max(holiday_end) as holiday_end
from (select lh.*, (@grp := @grp + group_flag) as grp
from (select lh.*,
(case when not exists (select 1
from lessons_holidays lh2
where lh2.holiday_begin <= lh.holiday_begin and
lh2.holiday_end > lh.holiday_begin and
lh2.holiday_begin <> lh.holiday_begin and
lh2.holiday_end <> lh.holiday_end
)
then 1 else 0
end) as group_flag
from lessons_holidays lh
) lh cross join
(select @grp := 0) params
order by holiday_begin, holiday_end
) lh
group by grp;
如图here.