सौभाग्य से, आप PostgreSQL का उपयोग कर रहे हैं। विंडो फ़ंक्शन generate_series()
आपका दोस्त है।
टेस्ट केस
निम्नलिखित परीक्षण तालिका को देखते हुए (जो आप प्रदान करना चाहिए था):
CREATE TABLE event(event_id serial, ts timestamp);
INSERT INTO event (ts)
SELECT generate_series(timestamp '2018-05-01'
, timestamp '2018-05-08'
, interval '7 min') + random() * interval '7 min';
हर 7 मिनट के लिए एक इवेंट (साथ ही 0 से 7 मिनट, बेतरतीब ढंग से)।
मूल समाधान
यह क्वेरी किसी भी मनमाने समय अंतराल के लिए घटनाओं की गणना करती है। उदाहरण में 17 मिनट:
WITH grid AS (
SELECT start_time
, lead(start_time, 1, 'infinity') OVER (ORDER BY start_time) AS end_time
FROM (
SELECT generate_series(min(ts), max(ts), interval '17 min') AS start_time
FROM event
) sub
)
SELECT start_time, count(e.ts) AS events
FROM grid g
LEFT JOIN event e ON e.ts >= g.start_time
AND e.ts < g.end_time
GROUP BY start_time
ORDER BY start_time;
-
क्वेरी न्यूनतम और अधिकतम
ts
. प्राप्त करती है आधार तालिका से पूर्ण समय सीमा को कवर करने के लिए। आप इसके बजाय एक मनमाना समय सीमा का उपयोग कर सकते हैं। -
कोई भी प्रदान करें समय अंतराल आवश्यकतानुसार।
-
हर . के लिए एक पंक्ति तैयार करता है टाइम स्लॉट। यदि उस अंतराल के दौरान कोई घटना नहीं हुई, तो गिनती
0
. है । -
ऊपरी और निचली सीमा को संभालना सुनिश्चित करें सही ढंग से:
- टाइमस्टैम्प के बीच SQL क्वेरी से अनपेक्षित परिणाम
-
विंडो फ़ंक्शन
lead()
इसमें अक्सर अनदेखी की गई विशेषता होती है:जब कोई अग्रणी पंक्ति मौजूद नहीं होती है तो यह डिफ़ॉल्ट प्रदान कर सकता है।'infinity'
प्रदान करना उदाहरण में। अन्यथा अंतिम अंतराल एक ऊपरी सीमा के साथ कट जाएगाNULL
।
न्यूनतम समकक्ष
ऊपर दी गई क्वेरी में CTE और lead()
का इस्तेमाल किया गया है और वर्बोज़ सिंटैक्स। सुरुचिपूर्ण और शायद समझने में आसान, लेकिन थोड़ा अधिक महंगा। यहाँ एक छोटा, तेज़, न्यूनतम संस्करण है:
SELECT start_time, count(e.ts) AS events
FROM (SELECT generate_series(min(ts), max(ts), interval '17 min') FROM event) g(start_time)
LEFT JOIN event e ON e.ts >= g.start_time
AND e.ts < g.start_time + interval '17 min'
GROUP BY 1
ORDER BY 1;
"पिछले सप्ताह में हर 15 मिनट में"` . के लिए उदाहरण
और to_char()
. के साथ फ़ॉर्मेटिंग करें ।
SELECT to_char(start_time, 'YYYY-MM-DD HH24:MI'), count(e.ts) AS events
FROM generate_series(date_trunc('day', localtimestamp - interval '7 days')
, localtimestamp
, interval '15 min') g(start_time)
LEFT JOIN event e ON e.ts >= g.start_time
AND e.ts < g.start_time + interval '15 min'
GROUP BY start_time
ORDER BY start_time;
अभी भी ORDER BY
और GROUP BY
अंतर्निहित टाइमस्टैम्प पर मान , स्वरूपित स्ट्रिंग पर नहीं। यह तेज़ और अधिक विश्वसनीय है।
db<>फिडल यहाँ
संबंधित उत्तर एक रनिंग काउंट producing उत्पन्न करता है समय सीमा में:
- PostgreSQL:किसी क्वेरी के लिए 'मिनट के हिसाब से' पंक्तियों की चल रही गिनती