MySQL - 排除冲突的日期范围

时间:2014-03-07 12:48:30

标签: mysql conflict date-range

想象一下这个日期范围列表

> SELECT * FROM range_table;
+----+------------+------------+
| id | start      | end        |
+----+------------+------------+
|  1 | 2014-01-01 | 2014-01-15 | /* -- Not conflicting */
|  2 | 2014-01-15 | 2014-01-16 | /* -- Conflicting     */
|  3 | 2014-01-15 | 2014-01-20 | /* |                  */
|  4 | 2014-01-15 | 2014-01-19 | /* /                  */
|  5 | 2014-01-24 | 2014-01-26 | /* -- Conflicting     */
|  6 | 2014-01-21 | 2014-01-25 | /* /                  */
+----+------------+------------+

我正在尝试删除冲突的范围,并且只保留每个冲突集的第一次出现。

这是我最后应该拥有的:

+----+------------+------------+
| id | start      | end        |
+----+------------+------------+
|  1 | 2014-01-01 | 2014-01-15 |
|  2 | 2014-01-15 | 2014-01-16 |
|  5 | 2014-01-24 | 2014-01-26 |
+----+------------+------------+

以下是fiddle

2 个答案:

答案 0 :(得分:1)

SELECT x.*
  FROM range_table x
  LEFT 
  JOIN range_table y
    ON y.start < x.end 
   AND y.end > x.start 
   AND y.id < x.id
 WHERE y.id IS NULL;

http://sqlfiddle.com/#!2/6f723/26

查询修改以适应明显修改的简要

答案 1 :(得分:0)

这是我可能的解决方案:

SELECT `id`, `start`, `end`
FROM (
  SELECT
    r1.id
  , r1.start
  , r1.end
  , COUNT(DISTINCT r2.id) AS "conflicts"
  , MD5(GROUP_CONCAT(DISTINCT r2.id ORDER BY r2.id)) AS "group_chksum"
  FROM range_table AS r1
  LEFT JOIN range_table AS r2
    ON (r1.end > r2.start AND r1.start < r2.end)
  GROUP BY r1.id
) AS tmp
GROUP BY group_chksum
;

我们的想法是按照范围的集合和MySQL的容忍度的优势对结果进行分组,以获取每个的结果。

我确信有更简单的