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

मैं एक महीने में उपयोग किए गए दिनों की कुल संख्या कैसे ज्ञात करूं?

डेटा का परीक्षण करें :

CREATE TABLE your_table ( usr, start_date, end_date ) AS (
  SELECT 'A', DATE '2017-06-01', DATE '2017-06-03' FROM DUAL UNION ALL
  SELECT 'B', DATE '2017-06-02', DATE '2017-06-04' FROM DUAL UNION ALL -- Overlaps previous
  SELECT 'C', DATE '2017-06-06', DATE '2017-06-06' FROM DUAL UNION ALL
  SELECT 'D', DATE '2017-06-07', DATE '2017-06-07' FROM DUAL UNION ALL -- Adjacent to previous
  SELECT 'E', DATE '2017-06-11', DATE '2017-06-20' FROM DUAL UNION ALL
  SELECT 'F', DATE '2017-06-14', DATE '2017-06-15' FROM DUAL UNION ALL -- Within previous
  SELECT 'G', DATE '2017-06-22', DATE '2017-06-25' FROM DUAL UNION ALL
  SELECT 'H', DATE '2017-06-24', DATE '2017-06-28' FROM DUAL UNION ALL -- Overlaps previous and next
  SELECT 'I', DATE '2017-06-27', DATE '2017-06-30' FROM DUAL UNION ALL
  SELECT 'J', DATE '2017-06-27', DATE '2017-06-28' FROM DUAL;          -- Within H and I          

क्वेरी :

SELECT SUM( days ) AS total_days
FROM   (
  SELECT dt - LAG( dt ) OVER ( ORDER BY dt ) + 1 AS days,
         start_end
  FROM   (
    SELECT dt,
           CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
             WHEN 1 THEN 'start'
             WHEN 0 THEN 'end'
           END AS start_end
    FROM   your_table
    UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
  )
  WHERE start_end IS NOT NULL
)
WHERE start_end = 'end';

आउटपुट :

TOTAL_DAYS
----------
        25

स्पष्टीकरण :

SELECT dt, value
FROM   your_table
UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )

यह UNPIVOT होगा तालिका ताकि प्रारंभ और समाप्ति तिथियां एक ही कॉलम में हों (dt ) और प्रारंभ के लिए +1 और समाप्ति तिथि के लिए -1 का संगत मान दिया जाता है।

SELECT dt,
       SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) AS total,
       value
FROM   your_table
UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )

प्रारंभ और समाप्ति तिथियां और उन जेनरेट किए गए मानों का संचयी योग देगा। किसी श्रेणी की शुरुआत में हमेशा value=1 होगा और total=1 और किसी श्रेणी के अंत में हमेशा total=0 होगा . यदि कोई तिथि किसी सीमा के बीच में है तो उसके पास total>1 होगा या value=-1 और total=1 . इसका उपयोग करके, यदि आप value को गुणा करते हैं और total तब एक श्रेणी की शुरुआत तब होती है जब value*total=1 और एक श्रेणी का अंत तब होता है जब value*total=0 और कोई भी अन्य मान उस तिथि को इंगित करता है जो एक सीमा के बीच में है।

यह क्या देता है:

SELECT dt,
       CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
         WHEN 1 THEN 'start'
         WHEN 0 THEN 'end'
       END AS start_end
FROM   your_table
UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )

फिर आप तारीखों को फ़िल्टर कर सकते हैं जब start_end NULL है जो आपको वैकल्पिक start . के साथ एक तालिका के साथ छोड़ देगा और end पंक्तियाँ जिनका आप उपयोग कर सकते हैं LAG दिनों के अंतर की गणना करने के लिए:

SELECT dt - LAG( dt ) OVER ( ORDER BY dt ) + 1 AS days,
       start_end
FROM   (
  SELECT dt,
         CASE SUM( value ) OVER ( ORDER BY dt ASC, value DESC, ROWNUM ) * value
           WHEN 1 THEN 'start'
           WHEN 0 THEN 'end'
         END AS start_end
  FROM   your_table
  UNPIVOT ( dt FOR value IN ( start_date AS 1, end_date AS -1 ) )
)
WHERE start_end IS NOT NULL

इसके बाद आपको केवल SUM . करना है end - start . के लिए सभी अंतर; जो ऊपर क्वेरी देता है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. जावा में ORACLE फ़ंक्शन MONTHS_BETWEEN का एनालॉग

  2. विंडोज 64 बिट के लिए Oracle 11g एक्सप्रेस संस्करण?

  3. Oracle डेटाबेस का उपयोग करते हुए Django निरीक्षणडीबी मुद्दा

  4. क्लॉज के साथ स्टेटमेंट अपडेट करें

  5. java.sql.SQLRecoverableException:नेटवर्क एडेप्टर कनेक्शन स्थापित नहीं कर सका