ये रहा एक तरीका।
टाइमस्टैम्प द्वारा स्थिति पंक्तियों को क्रम में प्राप्त करके प्रारंभ करें (इनलाइन दृश्य को s
. के रूप में उपनामित किया गया है ) फिर पिछली पंक्तियों से मान रखने के लिए MySQL उपयोगकर्ता चर का उपयोग करें, जैसा कि आप प्रत्येक पंक्ति के माध्यम से संसाधित करते हैं।
हम वास्तव में एक 'ऊपर' स्थिति की तलाश कर रहे हैं जो तुरंत 'नीचे' स्थिति के अनुक्रम का अनुसरण करती है। और जब हम उस पंक्ति को 'ऊपर' स्थिति के साथ पाते हैं, तो हमें वास्तव में 'डाउन' स्थिति की पिछली श्रृंखला से सबसे प्रारंभिक टाइमस्टैम्प की आवश्यकता होती है।
तो, कुछ इस तरह काम करेगा:
SELECT d.start_down
, d.ended_down
FROM (SELECT @i := @i + 1 AS i
, @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
, @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
, @status := s.status
FROM (SELECT t.time
, t.status
FROM mydata t
WHERE t.status IN ('up','down')
ORDER BY t.time ASC, t.status ASC
) s
JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i
) d
WHERE d.start_down IS NOT NULL
AND d.ended_down IS NOT NULL
यह आपके द्वारा दिखाए जाने वाले विशेष डेटा सेट के लिए काम करता है।
यह जो संभाल नहीं पाता है (जो वापस नहीं आता है) एक 'डाउन' अवधि है जो अभी समाप्त नहीं हुई है, यानी 'डाउन' स्थिति का एक क्रम जिसमें कोई 'अप' स्थिति नहीं है।
पंक्तियों को क्रम में वापस करने के लिए फाइलसॉर्ट ऑपरेशन से बचने के लिए, आप (time,status)
पर एक कवरिंग इंडेक्स चाहते हैं . यह क्वेरी d
के रूप में उपनामित इनलाइन दृश्य को मूर्त रूप देने के लिए एक अस्थायी (MyISAM) तालिका उत्पन्न करेगी ।
नोट: यह समझने के लिए कि यह क्वेरी क्या कर रही है, उस सबसे बाहरी क्वेरी को हटा दें, और d
के रूप में उपनामित इनलाइन दृश्य के लिए केवल क्वेरी चलाएँ (आप s.time
add जोड़ सकते हैं चयन सूची में।)
यह क्वेरी प्रत्येक पंक्ति को 'ऊपर' या 'नीचे' स्थिति के साथ प्राप्त कर रही है। "चाल" यह है कि यह केवल 'डाउन' अवधि को समाप्त करने वाली पंक्तियों पर "प्रारंभ" और "अंत" समय (डाउन अवधि को चिह्नित करना) दोनों निर्दिष्ट कर रहा है। (अर्थात, 'अप' स्थिति वाली पहली पंक्ति, 'डाउन' स्थिति के साथ पंक्तियों के बाद।) यह वह जगह है जहां वास्तविक कार्य किया जाता है, सबसे बाहरी क्वेरी इस परिणामसेट में सभी "अतिरिक्त" पंक्तियों को फ़िल्टर करती है (कि हम जरूरत नहीं है।)
SELECT @i := @i + 1 AS i
, @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down
, @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down
, @status := s.status
, s.time
FROM (SELECT t.time
, t.status
FROM mydata t
WHERE t.status IN ('up','down')
ORDER BY t.time ASC, t.status ASC
) s
JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i
इनलाइन दृश्य का उद्देश्य s
. के रूप में उपनामित है टाइमस्टैम्प मान द्वारा क्रमबद्ध पंक्तियों को प्राप्त करना है, इसलिए हम उन्हें क्रम में संसाधित कर सकते हैं। इनलाइन दृश्य को i
. के रूप में उपनामित किया गया है बस वहाँ है इसलिए हम क्वेरी की शुरुआत में कुछ उपयोगकर्ता चर शुरू कर सकते हैं।
यदि हम Oracle या SQL सर्वर पर चल रहे थे, तो हम "एनालिटिक फ़ंक्शंस" या "रैंकिंग फ़ंक्शंस" का उपयोग कर सकते थे (जैसा कि उन्हें क्रमशः नाम दिया गया है।) MySQL ऐसा कुछ भी प्रदान नहीं करता है, इसलिए हमें "अपना खुद का रोल करना होगा। ".