我有一个临时表,可用日期重叠。这些日期可以以任何方式组合重叠,因为它们适用于多个可用房间。
我想创建一个返回一组合并可用日期的查询。 (打开日期是可用日期;关闭不可用。)
例如,以下数据
+------------+------------+
| opens | closes |
+------------+------------+
| 2015-12-03 | 2015-12-05 |
| 2016-01-08 | 2016-01-15 |
| 2016-02-21 | 2016-02-27 |
| 2016-03-13 | 2016-03-24 |
| 2016-03-31 | 2016-04-02 |
| 2016-04-06 | 2016-04-15 |
| 2016-04-21 | 2016-12-03 |
| 2015-12-03 | 2015-12-09 |
| 2016-01-03 | 2016-01-06 |
| 2016-01-16 | 2016-02-08 |
| 2016-03-01 | 2016-03-06 |
| 2016-03-10 | 2016-12-03 |
+------------+------------+
应该返回:
+------------+------------+
| opens | closes |
+------------+------------+
| 2015-12-03 | 2015-12-09 |
| 2016-01-03 | 2016-01-06 |
| 2016-01-08 | 2016-01-15 |
| 2016-01-16 | 2016-02-08 |
| 2016-02-21 | 2016-02-27 |
| 2016-03-01 | 2016-03-06 |
| 2016-03-10 | 2016-12-03 |
+------------+------------+
感谢您的帮助!
答案 0 :(得分:3)
这样做的一种方法是使用相关子查询:
SELECT DISTINCT
(SELECT MIN(opens)
FROM mytable AS t2
WHERE t2.opens <= t1.closes AND t2.closes >= t1.opens) AS start,
(SELECT MAX(closes)
FROM mytable AS t2
WHERE t2.opens <= t1.closes AND t2.closes >= t1.opens) AS end
FROM mytable AS t1
ORDER BY opens
相关子查询的WHERE
谓词:
t2.opens <= t1.closes AND t2.closes >= t1.opens
返回与当前记录相关的所有重叠记录。在这些记录中执行聚合,我们可以找到每个间隔的开始/结束日期:间隔的开始日期是所有重叠记录之间的最小opens
日期,而结束日期是最大closes
日期
修改强>
上述解决方案无法使用如下所示的一系列间隔:
1. |-----------|
2. |----|
3. |-----|
记录号码2,处理时,会产生有缺陷的开始/结束间隔。
这是使用变量的解决方案:
SELECT MIN(start) AS start, MAX(end) AS end
FROM (
SELECT @grp := IF(@start = '1900-01-01' OR
(opens <= @end AND closes >= @start), @grp, @grp+1) AS grp,
@start := IF(@start = '1900-01-01', opens,
IF(opens <= @end AND closes >= @start,
IF (@start < opens, @start, opens), opens)) AS start,
@end := IF(@end = '1900-01-01', closes,
IF (opens <= @end AND closes >= @start,
IF (@end > closes, @end, closes), closes)) AS end
FROM mytable
CROSS JOIN (SELECT @grp := 1, @start := '1900-01-01', @end := '1900-01-01') AS vars
ORDER BY opens, DATEDIFF(closes, opens) DESC) AS t
GROUP BY grp
这个想法是从最左边的opens/closes
间隔开始。变量@start
,@end
用于传播增量扩展(当正在处理新的重叠行时)在间隔链中的合并间隔。遇到非重叠间隔后,会初始化[@start - @end]
以匹配此新间隔,grp
会增加1。