PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

रेल + पोस्टग्रेस में मनमाने समय अंतराल द्वारा रिकॉर्ड गिनने का सबसे अच्छा तरीका

सौभाग्य से, आप 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:किसी क्वेरी के लिए 'मिनट के हिसाब से' पंक्तियों की चल रही गिनती



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. pg_restore विकल्प - PostgreSQL बैकअप और ClusterControl के साथ स्वचालित पुनर्प्राप्ति

  2. दी गई तालिका के लिए स्तंभों के गतिशील सेट को वापस करने का कार्य

  3. क्या PostgreSQL में सरणी तत्वों पर एक विशिष्टता बाधा हो सकती है?

  4. PostgreSQL में NULL की n पंक्तियाँ उत्पन्न करें

  5. कैसे Pi () PostgreSQL में काम करता है