ऐसा करने का एक तरीका सहसंबद्ध उपश्रेणियों का उपयोग करना है:
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 t1
ORDER BY opens
WHERE
सहसंबद्ध उपश्रेणियों की विधेय:
t2.opens <= t1.closes AND t2.closes >= t1.opens
वर्तमान रिकॉर्ड से संबंधित सभी अतिव्यापी रिकॉर्ड लौटाएं। इन रिकॉर्डों को एकत्र करने से हम प्रत्येक अंतराल की शुरुआत / समाप्ति तिथियां पा सकते हैं:अंतराल की शुरुआत की तारीख न्यूनतम opens
है सभी अतिव्यापी रिकॉर्ड के बीच की तारीख, जबकि अंतिम तिथि अधिकतम closes
है तारीख।
संपादित करें:
उपरोक्त समाधान निम्न जैसे अंतरालों के सेट के साथ काम नहीं करेगा:
1. |-----------|
2. |----|
3. |-----|
रिकॉर्ड नं। 2, संसाधित होने पर, एक त्रुटिपूर्ण प्रारंभ/समाप्ति अंतराल उत्पन्न करेगा।
यहां वेरिएबल का उपयोग करके समाधान दिया गया है:
SELECT MIN(start) AS start, MAX(end) AS end
FROM (
SELECT @grp := IF(@start = '1900-01-01' OR
(opens <= @end AND closes >= @start), @grp, @grp+1) AS grp,
@start := IF(@start = '1900-01-01', opens,
IF(opens <= @end AND closes >= @start,
IF (@start < opens, @start, opens), opens)) AS start,
@end := IF(@end = '1900-01-01', closes,
IF (opens <= @end AND closes >= @start,
IF (@end > closes, @end, closes), closes)) AS end
FROM mytable
CROSS JOIN (SELECT @grp := 1, @start := '1900-01-01', @end := '1900-01-01') AS vars
ORDER BY opens, DATEDIFF(closes, opens) DESC) AS t
GROUP BY grp
विचार सबसे बाईं ओर से शुरू करना है opens/closes
मध्यान्तर। चर @start
, @end
वृद्धिशील रूप से विस्तार करने के लिए उपयोग किया जाता है (जैसा कि नई ओवरलैपिंग पंक्तियों को संसाधित किया जा रहा है) समेकित अंतराल अंतराल श्रृंखला के नीचे। एक बार गैर-अतिव्यापी अंतराल का सामना करने के बाद, [@start - @end]
इस नए अंतराल और grp
. से मेल खाने के लिए इनिशियलाइज़ किया गया है एक से बढ़ा दिया गया है।