Един от начините да го направите е чрез използване на корелирани подзаявки:
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 t1ORDER BY отваря
WHERE
предикати на корелираните подзаявки:
t2.opens <=t1.closes И t2.closes>=t1.opens
връща всички припокриващи се записи, свързани с текущия запис. Извършвайки агрегиране на тези записи, можем да намерим началната/крайната дата на всеки интервал:началната дата на интервала е минималното отваряне
дата между всички припокриващи се записи, докато крайната дата е максималната затваря
дата.
РЕДАКТИРАНЕ:
Горното решение няма да работи с набор от интервали като следния:
<предварителен код>1. |-----------|2. |----|3. |-----|Запис № 2, когато се обработва, ще произведе грешен начален/краен интервал.
Ето решение, използващо променливи:
SELECT MIN(start) AS start, MAX(end) AS endFROM ( SELECT @grp :=IF(@start ='1900-01-01' OR (отваря <=@end И затваря>=@ начало), @grp, @grp+1) AS grp, @start :=IF(@start ='1900-01-01', отваря, IF(отваря <=@end И затваря>=@start, IF (@ start <отваря, @start, отваря), отваря)) AS start, @end :=IF(@end ='1900-01-01', затваря, IF (отваря <=@end И затваря>=@start, IF (@end> затваря, @end, затваря), затваря)) КАТО край ОТ mytable CROSS JOIN (ИЗБЕРЕТЕ @grp :=1, @start :='1900-01-01', @end :='1900-01- 01') AS vars ORDER BY отваря, DATEDIFF(затваря, отваря) DESC) AS tGROUP BY grp
Идеята е да започнете от най-ляво отваря/затваря
интервал. Променливи @start
, @end
се използват за разпространение на постепенно разширяващия се (тъй като се обработват нови припокриващи се редове) консолидиран интервал надолу по интервалната верига. След като бъде открит интервал без припокриване, [@start - @end]
се инициализира така, че да съответства на този нов интервал и grp
се увеличава с единица.