एक ही कॉलम के भीतर दिनांक का योग अंतराल


10

इंटरलेयिंग पंक्तियों के बीच एक ही कॉलम में दिनांक की श्रेणी के अंतर को आप कैसे सबसे अच्छा मानते हैं? मेरे पास एक डेटाटाइम कॉलम है और पंक्तियों के बीच के अंतर की गणना करना चाहते हैं। मैं सेकंड में अंतर चाहता हूं। यह प्रश्न 2 टाइमस्टैम्प के बीच अंतर प्राप्त करने के तरीके के बारे में नहीं है, बल्कि एक ही टेबल पर पंक्तियों के बीच सबसे कुशलता से गणना करने के तरीके पर अधिक केंद्रित है। मेरे मामले में प्रत्येक पंक्ति में एक डेटाइम इवेंटाइप है जो तार्किक रूप से 2 पंक्तियों को एक साथ जोड़ता है।

विवरण प्रारंभ और समाप्ति के ईवेंट समूह को कैसे व्यवस्थित करें, इससे संबंधित। (एंड्री एम का प्रश्न) प्रारंभ और अंत "" लगातार होना चाहिए। यदि प्रारंभ में बाद का अंत नहीं है, तो उसे योग से छोड़ा जाना चाहिए। अगले पर जाना शुरू करें यह देखने के लिए कि क्या इसका अंत है। केवल लगातार शुरू - अंत जोड़े को कुल सेकंड के योग में जोड़ा जाना चाहिए।

Postgresql 9.x में कार्य करना ...

तालिका में उदाहरण डेटा;

eventtype, eventdate
START, 2015-01-01 14:00
END, 2015-01-01 14:25
START, 2015-01-01 14:30
END, 2015-01-01 14:43
START, 2015-01-01 14:45
END, 2015-01-01 14:49
START, 2015-01-01 14:52
END, 2015-01-01 14:55

नोट, ऑल स्टार्ट एंड एंड डेट्स क्रमिक होंगे।

यहाँ मेरा पहला प्रयास है। काम करने लगता है।

SELECT 
-- starts.*
SUM(EXTRACT(EPOCH FROM (eventdate_next - eventdate))) AS duration_seconds
FROM
( 
    WITH x AS (
        SELECT *, dense_rank() OVER (ORDER BY eventdate) AS rnk
        FROM   table
        AND eventdate > '2015-01-01 00:00:00.00'
        AND eventdate < '2016-01-01 23:59:59.59' 
        )
    SELECT x.eventdate, x.eventtype, y.eventdate AS eventdate_next,  y.eventtype AS eventtype_next
    FROM   x
    LEFT   JOIN (SELECT DISTINCT eventdate, eventtype, rnk FROM x) y ON y.rnk = (x.rnk + 1)
    ORDER  BY x.eventdate
) starts
WHERE
eventtype = 'START'   
GROUP BY eventtype 

मेरा पहला प्रयास स्टैकओवरफ्लो पोस्टग्रेज 9.1 से एक महान उदाहरण पर आधारित है - अगला मूल्य प्राप्त करना

ध्यान दें; आप ग्रुप बीवाई और एसयूएम पर टिप्पणी कर सकते हैं और शुरू होने वाली टिप्पणी कर सकते हैं। * राशि में जाने वाले प्रत्येक व्यक्ति की अवधि के लिए रिकॉर्ड प्राप्त करने के लिए।

जवाबों:


10

आप LEADअगली पंक्ति के eventtypeऔर eventdateवर्तमान पंक्ति के डेटा को प्राप्त करने के लिए विश्लेषणात्मक फ़ंक्शन का उपयोग कर सकते हैं :

SELECT
  eventtype,
  eventdate,
  LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
  LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
FROM
  atable
WHERE
      eventdate >= '2015-01-01 00:00:00.00'
  AND eventdate <  '2016-01-01 23:59:59.59'

उपरोक्त क्वेरी का उपयोग एक व्युत्पन्न तालिका के रूप में, आप आउटपुट को आगे फ़िल्टर कर सकते हैं eventtype = 'START' AND nexttype = 'END'और कुल अंतर प्राप्त कर सकते हैं :

SELECT
  SUM(EXTRACT(EPOCH FROM (nextdate - eventdate))) AS duration_seconds
FROM
  (
    SELECT
      eventtype,
      eventdate,
      LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
      LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
    FROM
      atable
    WHERE
          eventdate >= '2015-01-01 00:00:00.00'
      AND eventdate <  '2016-01-01 23:59:59.59'
  ) AS s
WHERE
      eventtype = 'START'
  AND nexttype  = 'END'
;

थोड़ी भिन्नता के रूप में, आप एक CTE के रूप में उपकुंजी को लागू कर सकते हैं:

WITH cte AS
  (
    SELECT
      eventtype,
      eventdate,
      LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
      LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
    FROM
      atable
    WHERE
          eventdate >= '2015-01-01 00:00:00.00'
      AND eventdate <  '2016-01-01 23:59:59.59'
  )
SELECT
  SUM(EXTRACT(EPOCH FROM (nextdate - eventdate))) AS duration_seconds
FROM
  cte
WHERE
      eventtype = 'START'
  AND nexttype  = 'END'
;

इस पुनर्लेखन में प्रदर्शन के लिए निहितार्थ हो सकते हैं, क्योंकि एक व्युत्पन्न तालिका के विपरीत, PostgreSQL में एक सीटीई सामग्री है। यदि कोई अंतर है और यदि हां, तो आपके लिए कौन सा विकल्प बेहतर है, इसका परीक्षण करना चाहिए।


एंड्री, धन्यवाद! मैं सीटीई संस्करण की कोशिश करूंगा और देखूंगा कि यह कैसे मदद करता है।
सी स्मिथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.