आप एक चर के साथ संयोजन के रूप में एक स्थानांतरित स्व-बाहरी-जुड़ने का उपयोग करके इसे पूरा कर सकते हैं। यह समाधान देखें:
SELECT IF(COUNT(1) > 0, 1, 0) AS has_consec
FROM
(
SELECT *
FROM
(
SELECT IF(b.login_date IS NULL, @val:[email protected]+1, @val) AS consec_set
FROM tbl a
CROSS JOIN (SELECT @val:=0) var_init
LEFT JOIN tbl b ON
a.user_id = b.user_id AND
a.login_date = b.login_date + INTERVAL 1 DAY
WHERE a.user_id = 1
) a
GROUP BY a.consec_set
HAVING COUNT(1) >= 30
) a
यह या तो 1
लौटाएगा या एक 0
इस आधार पर कि क्या उपयोगकर्ता ने किसी भी समय . पर लगातार 30 दिनों या उससे अधिक समय तक लॉग इन किया है पिछले।
इस क्वेरी का खामियाजा वास्तव में पहले उप-चयन में है। आइए करीब से देखें ताकि हम बेहतर ढंग से समझ सकें कि यह कैसे काम करता है:
निम्न उदाहरण डेटा सेट के साथ:
CREATE TABLE tbl (
user_id INT,
login_date DATE
);
INSERT INTO tbl VALUES
(1, '2012-04-01'), (2, '2012-04-02'),
(1, '2012-04-25'), (2, '2012-04-03'),
(1, '2012-05-03'), (2, '2012-04-04'),
(1, '2012-05-04'), (2, '2012-05-04'),
(1, '2012-05-05'), (2, '2012-05-06'),
(1, '2012-05-06'), (2, '2012-05-08'),
(1, '2012-05-07'), (2, '2012-05-09'),
(1, '2012-05-09'), (2, '2012-05-11'),
(1, '2012-05-10'), (2, '2012-05-17'),
(1, '2012-05-11'), (2, '2012-05-18'),
(1, '2012-05-12'), (2, '2012-05-19'),
(1, '2012-05-16'), (2, '2012-05-20'),
(1, '2012-05-19'), (2, '2012-05-21'),
(1, '2012-05-20'), (2, '2012-05-22'),
(1, '2012-05-21'), (2, '2012-05-25'),
(1, '2012-05-22'), (2, '2012-05-26'),
(1, '2012-05-25'), (2, '2012-05-27'),
(2, '2012-05-28'),
(2, '2012-05-29'),
(2, '2012-05-30'),
(2, '2012-05-31'),
(2, '2012-06-01'),
(2, '2012-06-02');
यह प्रश्न:
SELECT a.*, b.*, IF(b.login_date IS NULL, @val:[email protected]+1, @val) AS consec_set
FROM tbl a
CROSS JOIN (SELECT @val:=0) var_init
LEFT JOIN tbl b ON
a.user_id = b.user_id AND
a.login_date = b.login_date + INTERVAL 1 DAY
WHERE a.user_id = 1
उत्पादन करेंगे:
जैसा कि आप देख सकते हैं, हम जो कर रहे हैं वह है स्थानांतरित करना +1 दिन तक तालिका में शामिल हुआ। प्रत्येक दिन के लिए जो पहले दिन के साथ लगातार नहीं है, एक NULL
मान लेफ्ट जॉइन द्वारा उत्पन्न होता है।
अब जबकि हम जानते हैं जहां लगातार दिन होते हैं, हम प्रत्येक सेट . में अंतर करने के लिए एक चर का उपयोग कर सकते हैं यह पता लगाकर कि शिफ्ट की गई तालिका की पंक्तियाँ NULL
हैं या नहीं, लगातार दिनों तक . अगर वे NULL
हैं , दिन लगातार नहीं होते हैं, इसलिए केवल चर बढ़ाएँ। यदि वे NOT NULL
, फिर वेरिएबल में वृद्धि न करें:
जब हम लगातार दिनों के प्रत्येक सेट को वृद्धिशील चर के साथ अलग कर देते हैं, तो यह प्रत्येक "सेट" द्वारा समूहीकृत करने का एक साधारण मामला है (जैसा कि consec_set
में परिभाषित किया गया है) कॉलम) और HAVING
. का उपयोग कर रहे हैं निर्दिष्ट लगातार दिनों से कम वाले किसी भी सेट को फ़िल्टर करने के लिए (आपके उदाहरण में 30):
फिर अंत में, हम कि को लपेटते हैं क्वेरी करें और केवल उन सेटों की संख्या गिनें जिनमें लगातार 30 या अधिक दिन थे। यदि इनमें से एक या अधिक सेट थे, तो 1
लौटाएं , अन्यथा 0
return लौटाएं ।