确定日期范围是否包含在MySQL的另一个范围内

时间:2017-01-25 20:03:46

标签: mysql sql

我正在寻找一种以“干净”的方式做到这一点的方法(不是3..n交叉JOINS),只是想知道是否可以在sql中执行此操作,如果不是,我会去另一个解。 将使用数字而不是日期来简化 我有n行n个任务和n个项目

 task  item   start end
    1     1      1     5
    1     2      2     6
    1     3      0     4
    1     4      8    10

在这种情况下,我希望使用重叠日期的min(start)max(end),结果将是:

task   item  start end
   1   1,2,3     0    6
   1       4     8   10

如何在sql中解决它的任何想法?就像一个挑战,如果不能这样做,我会去python。

谢谢

1 个答案:

答案 0 :(得分:0)

这类似于我回答here的问题,以及类似的数据“孤岛”问题。但是,在你的情况下它更复杂,因为“岛屿”的识别需要从不仅仅是之前的记录中计算出来。

它最终会看起来像这样:

SET @iEnd = -1; /* init value should be something you don't expect to see */
SET @task = -1; /* init value should be something you don't expect to see */
SET @isNewIsland = 0 /* init value doesn't actually matter */;
SET @i = 0;

SELECT islandNum
   , GROUP_CONCAT(item ORDER BY item) AS items
   , MIN(start) AS iStart
   , MAX(end) AS iEnd
FROM (
    SELECT @isNewIsland := IF(@task <> task OR start > @iEnd, 1, 0)
       , @task := task, item, start, end
       , @i := IF(@isNewIsland = 1, @i + 1, @i) AS islandNum
       , @end := IF(@isNewIsland = 1, end, GREATEST(end, @iEnd))
    FROM ( /* Session(@) variables evaluation can be a bit unpredictable
              the subquery helps guarantee ordering before evaluation */
        SELECT task, item, start, end
        FROM theTable
        ORDER BY task, start, end
    ) AS subQ
) AS subQ 2

有些人不喜欢需要单独的,在前的SET语句;为避免这种需要,请将) AS subQ替换为 ) AS subQ, (SELECT @iEnd := -1, @task := -1, @isNewIsland := 0, @i := 0) AS sInit