"साप्ताहिक औसत उपयोगकर्ता" गणना प्राप्त करने के लिए (आपके विनिर्देश के बारे में मेरी समझ के अनुसार... "प्रत्येक दिन के लिए, उस दिन और पिछले छह दिनों के दौरान देखी गई अलग-अलग उपयोगकर्ता_आईडी की संख्या"), नीचे दिए गए की तर्ज पर एक प्रश्न इस्तेमाल किया जा सकता है। (क्वेरी "दैनिक औसत उपयोगकर्ता" की संख्या भी लौटाती है।
SELECT d.day
, COUNT(DISTINCT u.user_id) AS wau
, COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
FROM ( SELECT FLOOR(k.ts/86400) AS `day`
FROM `log` k
GROUP BY `day`
) d
JOIN ( SELECT FLOOR(l.ts/86400) AS `day`
, l.user_id
FROM `log` l
GROUP BY `day`, l.user_id
) u
ON u.day <= d.day
AND u.day > d.day - 7
GROUP BY d.day
ORDER BY d.day
(मैंने अभी तक इसका परीक्षण नहीं किया है, लेकिन मैं बाद में करूंगा, और अगर किसी सुधार की आवश्यकता होगी तो मैं इस कथन को अपडेट करूंगा।)
यह क्वेरी किसी दिए गए दिन के लिए उपयोगकर्ताओं की सूची में शामिल हो रही है (u
. से) Rowsource), लॉग टेबल से दिनों के एक सेट के लिए (d
पंक्ति स्रोत)। शाब्दिक "7" पर ध्यान दें जो जॉइन विधेय (ऑन क्लॉज) में दिखाई देता है, यही उपयोगकर्ता सूची को पिछले 6 दिनों से "मिलान" कर रहा है।
ध्यान दें कि पिछले 3 दिनों में विशिष्ट उपयोगकर्ता संख्या प्राप्त करने के लिए इसे बढ़ाया भी जा सकता है, उदाहरण के लिए, चयन सूची में एक और अभिव्यक्ति जोड़कर।
, COUNT(DISTINCT IF(u.day<=d.day AND u.day>d.day-3,u.user_id,NULL)) AS 3day
एक बड़ी रेंज पाने के लिए उस शाब्दिक "7" को बढ़ाया जा सकता है। और ऊपर दिए गए व्यंजक में उस शाब्दिक 3 को किसी भी दिन प्राप्त करने के लिए बदला जा सकता है... हमें बस यह सुनिश्चित करने की आवश्यकता है कि हमारे पास पिछले दिन की पर्याप्त पंक्तियां हैं (d
से) ) u
. से प्रत्येक पंक्ति में शामिल हुए ।
प्रदर्शन नोट:इनलाइन दृश्यों (या व्युत्पन्न तालिकाओं के कारण, जैसा कि MySQL उन्हें कॉल करता है), यह क्वेरी बहुत तेज़ नहीं हो सकती है, क्योंकि उन इनलाइन दृश्यों के परिणामों को इंटरमीडिएट MyISAM तालिकाओं में परिवर्तित किया जाना है।
इनलाइन दृश्य को u
. के रूप में उपनामित किया गया है इष्टतम नहीं हो सकता है; सीधे लॉग तालिका में शामिल होना तेज़ हो सकता है। मैं किसी दिए गए दिन के लिए उपयोगकर्ताओं की एक अनूठी सूची प्राप्त करने के संदर्भ में सोच रहा था, जो कि इनलाइन दृश्य में उस क्वेरी ने मुझे प्राप्त किया। मेरे लिए यह समझना आसान था कि क्या हो रहा था। और मैं सोच रहा था कि यदि आपके पास एक ही उपयोगकर्ता के सैकड़ों दिन के लिए प्रवेश किया गया था, तो इनलाइन दृश्य डुप्लिकेट के पूरे समूह को हटा देगा, इससे पहले कि हम अन्य दिनों में शामिल हों। एक WHERE क्लॉज दिनों की संख्या को सीमित करने के लिए हम लौट रहे हैं, उन्हें u
. के अंदर सबसे अच्छा जोड़ा जाएगा और d
इनलाइन दृश्य। (d
इनलाइन दृश्य में पहले के 6 दिन अतिरिक्त शामिल करने होंगे।)
एक अन्य नोट पर, यदि ts कॉलम TIMESTAMP डेटाटाइप है, तो मैं DATE(ts)
का उपयोग करने के लिए अधिक इच्छुक हूं। दिनांक भाग निकालने के लिए अभिव्यक्ति। लेकिन वह एक पूर्णांक के बजाय परिणामसेट में एक DATE डेटाटाइप लौटाएगा, जो आपके द्वारा निर्दिष्ट परिणामसेट से अलग होगा।)
SELECT d.day
, COUNT(DISTINCT u.user_id) AS wau
, COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
FROM ( SELECT DATE(k.ts) AS `day`
FROM `log` k
GROUP BY `day`
) d
JOIN ( SELECT DATE(l.ts) AS `day`
, l.user_id
FROM `log` l
GROUP BY `day`, l.user_id
) u
ON u.day <= d.day
AND u.day > DATE_ADD(d.day, INTERVAL -7 DAY)
GROUP BY d.day
ORDER BY d.day