我正在寻找一种以“干净”的方式做到这一点的方法(不是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。
谢谢
答案 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