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

Oracle SQL - महीने के अनुसार दो तारीखों के बीच उपयोगकर्ताओं का चयन करें

यह क्वेरी महीने के अंत तक सक्रिय-उपयोगकर्ता-गणना को प्रभावी दिखाती है।

यह कैसे काम करता है:

  1. प्रत्येक इनपुट पंक्ति को रूपांतरित करें (StartDate . के साथ) और EndDate मान) दो . में पंक्तियाँ जो उस बिंदु-समय का प्रतिनिधित्व करती हैं जब सक्रिय-उपयोगकर्ता-गणना में वृद्धि हुई (StartDate पर) ) और घटा हुआ (EndDate . पर) ) हमें NULL को कन्वर्ट करने की जरूरत है दूर दिनांक मान के लिए क्योंकि NULL मानों को गैर-NULL . के बाद के बजाय पहले क्रमबद्ध किया जाता है मान:

    इससे आपका डेटा इस तरह दिखता है:

    OnThisDate   Change
    2018-01-01        1
    2019-01-01       -1
    2018-01-01        1
    9999-12-31       -1
    2019-01-01        1
    2019-06-01       -1
    2017-01-01        1
    2019-03-01       -1
    
  2. फिर हम बस SUM OVER Change मान (सॉर्ट करने के बाद) उस विशिष्ट तिथि के अनुसार सक्रिय-उपयोगकर्ता-गणना प्राप्त करने के लिए:

    तो सबसे पहले, OnThisDate . के आधार पर छाँटें :

    OnThisDate   Change
    2017-01-01        1
    2018-01-01        1
    2018-01-01        1
    2019-01-01        1
    2019-01-01       -1
    2019-03-01       -1
    2019-06-01       -1
    9999-12-31       -1
    

    फिर SUM OVER :

    OnThisDate   ActiveCount
    2017-01-01             1
    2018-01-01             2
    2018-01-01             3
    2019-01-01             4
    2019-01-01             3
    2019-03-01             2
    2019-06-01             1
    9999-12-31             0
    
  3. फिर हम PARTITION (समूह नहीं!) पंक्तियों को महीने के अनुसार और उन्हें उनकी तिथि के अनुसार क्रमबद्ध करें ताकि हम अंतिम ActiveCount की पहचान कर सकें उस महीने के लिए पंक्ति (यह वास्तव में WHERE . में होता है ROW_NUMBER() . का उपयोग करके सबसे बाहरी क्वेरी का और COUNT() प्रत्येक माह के लिए PARTITION ):

    OnThisDate   ActiveCount    IsLastInMonth
    2017-01-01             1                1
    2018-01-01             2                0
    2018-01-01             3                1
    2019-01-01             4                0
    2019-01-01             3                1
    2019-03-01             2                1
    2019-06-01             1                1
    9999-12-31             0                1
    
  4. फिर उस पर फ़िल्टर करें जहां IsLastInMonth = 1 (वास्तव में, जहां ROW_COUNT() = COUNT(*) प्रत्येक PARTITION . के अंदर ) हमें अंतिम आउटपुट डेटा देने के लिए:

    At-end-of-month     Active-count
    2017-01                        1
    2018-01                        3
    2019-01                        3
    2019-03                        2
    2019-06                        1
    9999-12                        0
    

इसका परिणाम परिणाम-सेट में "अंतराल" के रूप में होता है क्योंकि At-end-of-month कॉलम केवल उन पंक्तियों को दिखाता है जहां Active-count मूल्य वास्तव में सभी संभावित कैलेंडर महीनों को शामिल करने के बजाय बदल गया है - लेकिन यह आदर्श है (जहां तक ​​​​मेरा संबंध है) क्योंकि इसमें अनावश्यक डेटा शामिल नहीं है। प्रत्येक अतिरिक्त महीने के लिए आउटपुट पंक्तियों को तब तक दोहराते हुए जब तक कि यह अगले At-end-of-month तक न पहुंच जाए, आपके एप्लिकेशन कोड के भीतर अंतरालों को भरना किया जा सकता है। मूल्य।

एसक्यूएल सर्वर पर टी-एसक्यूएल का उपयोग कर क्वेरी यहां दी गई है (मेरे पास अभी ओरेकल तक पहुंच नहीं है)। और यहाँ SQLFiddle मैं एक समाधान के लिए आया करता था:http://sqlfiddle.com/# !18/ad68b7/24

SELECT
  OtdYear,
  OtdMonth,
  ActiveCount
FROM
  (

    -- This query adds columns to indicate which row is the last-row-in-month ( where RowInMonth == RowsInMonth )
    SELECT
      OnThisDate,
      OtdYear,
      OtdMonth,
      ROW_NUMBER() OVER ( PARTITION BY OtdYear, OtdMonth ORDER BY OnThisDate ) AS RowInMonth,
      COUNT(*) OVER ( PARTITION BY OtdYear, OtdMonth ) AS RowsInMonth,
      ActiveCount
    FROM
      (
        SELECT
          OnThisDate,
          YEAR( OnThisDate ) AS OtdYear,
          MONTH( OnThisDate ) AS OtdMonth,
          SUM( [Change] ) OVER ( ORDER BY OnThisDate ASC ) AS ActiveCount
        FROM
          (
            SELECT
              StartDate AS [OnThisDate],
              1 AS [Change]
            FROM
              tbl

            UNION ALL

            SELECT
              ISNULL( EndDate, DATEFROMPARTS( 9999, 12, 31 ) ) AS [OnThisDate],
              -1 AS [Change]
            FROM
              tbl
          ) AS sq1
      ) AS sq2
  ) AS sq3
WHERE
  RowInMonth = RowsInMonth
ORDER BY
  OtdYear,
  OtdMonth

यह क्वेरी कर सकते हैं एलियासेस (जैसे OtdYear) का उपयोग करने के बजाय सीधे एग्रीगेट और विंडो फ़ंक्शंस का उपयोग करके कम नेस्टेड प्रश्नों में फ़्लैट किया जाए , ActiveCount , आदि) लेकिन इससे क्वेरी को समझना बहुत कठिन हो जाएगा।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. लॉन्ग को Varchar2 में कनवर्ट करना

  2. कैसे SID Oracle में सेवा नाम से अलग है tnsnames.ora

  3. Oracle SQL डेवलपर में पैकेज कैसे बनाएं?

  4. HEXTORAW () Oracle में फ़ंक्शन

  5. Oracle JDBC UCP और Java