我正在寻找一种以“干净”的方式执行此操作的方法(不是 3..n 交叉联接),只是想知道是否可以在 sql 中执行此操作,如果不能,我会选择另一个方法解决方案。 为了简化将使用数字而不是日期 我有 n 行,包含 n 个任务和 n 个项目
task item start end
1 1 1 5
1 2 2 6
1 3 0 4
1 4 8 10
在这种情况下,我希望使用重叠日期的最小值(开始)最大值(结束),因此结果将是:
task item start end
1 1,2,3 0 6
1 4 8 10
关于如何在sql中解决这个问题有什么想法吗?就像一个挑战,如果不能这样做,我就会去Python。
谢谢
最佳答案
这与我回答的问题类似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
关于mysql - 确定日期范围是否包含在 MySQL 中的另一个范围中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41860655/