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

Oracle SQL का उपयोग करके कुछ तार्किक नेटिंग के साथ रोलअप क्वेरी

मुझे पता है कि यह एक पुराना सवाल है और यह मूल पोस्टर के काम नहीं आएगा, लेकिन मैं इस पर एक स्टैब लेना चाहता था क्योंकि यह एक दिलचस्प सवाल था। मैंने इसका पर्याप्त परीक्षण नहीं किया, इसलिए मुझे उम्मीद है कि इसे अभी भी ठीक करने और ट्यून करने की आवश्यकता है। लेकिन मेरा मानना ​​है कि दृष्टिकोण वैध है। मैं किसी उत्पाद में इस तरह की क्वेरी का उपयोग करने की अनुशंसा नहीं करता क्योंकि इसे बनाए रखना या समझना मुश्किल होगा (और मुझे विश्वास नहीं है कि यह वास्तव में स्केलेबल है)। आप कुछ वैकल्पिक डेटा संरचनाएँ बनाने से बहुत बेहतर होंगे। ऐसा कहने के बाद, मैंने Postgresql 9.1 में यही चलाया:

    WITH x AS (
        SELECT round, action
              ,ABS(shares) AS shares
              ,profitpershare
              ,COALESCE( SUM(shares) OVER(ORDER BY round, action
                                          ROWS BETWEEN UNBOUNDED PRECEDING 
                                                   AND 1 PRECEDING)
                        , 0) AS previous_net_shares
              ,COALESCE( ABS( SUM(CASE WHEN action = 'SELL' THEN shares ELSE 0 END)
                            OVER(ORDER BY round, action
                                     ROWS BETWEEN UNBOUNDED PRECEDING 
                                              AND 1 PRECEDING) ), 0 ) AS previous_sells
          FROM AuctionResults
          ORDER BY 1,2
    )

    SELECT round, shares * profitpershare - deduction AS net
      FROM (

           SELECT buy.round, buy.shares, buy.profitpershare
                 ,SUM( LEAST( LEAST( sell.shares, GREATEST(buy.shares - (sell.previous_sells - buy.previous_sells), 0)
                                    ,GREATEST(sell.shares + (sell.previous_sells - buy.previous_sells) - buy.previous_net_shares, 0)
                                   )
                             ) * sell.profitpershare ) AS deduction
             FROM x buy
                 ,x sell
             WHERE sell.round > buy.round
               AND buy.action = 'BUY'
               AND sell.action = 'SELL'
             GROUP BY buy.round, buy.shares, buy.profitpershare

           ) AS y

और परिणाम:

     round | net
    -------+-----
         1 | 780
         2 | 420
    (2 rows)

इसे टुकड़ों में बांटने के लिए, मैंने इस डेटा सेट के साथ शुरुआत की:

    CREATE TABLE AuctionResults( round int, action varchar(4), shares int, profitpershare int);

    INSERT INTO AuctionResults VALUES(1, 'BUY', 6, 200);
    INSERT INTO AuctionResults VALUES(2, 'BUY', 5, 100);
    INSERT INTO AuctionResults VALUES(2, 'SELL',-2, 50);
    INSERT INTO AuctionResults VALUES(3, 'SELL',-5, 80);
    INSERT INTO AuctionResults VALUES(4, 'SELL', -4, 150);  

    select * from auctionresults;

     round | action | shares | profitpershare
    -------+--------+--------+----------------
         1 | BUY    |      6 |            200
         2 | BUY    |      5 |            100
         2 | SELL   |     -2 |             50
         3 | SELL   |     -5 |             80
         4 | SELL   |     -4 |            150
    (5 rows)

"WITH" क्लॉज में क्वेरी टेबल में कुछ रनिंग टोटल जोड़ती है।

  • "पिछला_नेट_शेयर" इंगित करता है कि वर्तमान रिकॉर्ड से पहले कितने शेयर बेचने के लिए उपलब्ध हैं। यह मुझे यह भी बताता है कि इस 'खरीद' को आवंटित करने से पहले मुझे कितने 'सेल' शेयरों को छोड़ना होगा।
  • "previous_sells" सामने आए "SELL" शेयरों की संख्या की एक चालू गणना है, इसलिए दो "previous_sells" के बीच का अंतर उस समय में उपयोग किए गए 'SELL' शेयरों की संख्या को दर्शाता है।

     round | action | shares | profitpershare | previous_net_shares | previous_sells
    -------+--------+--------+----------------+---------------------+----------------
         1 | BUY    |      6 |            200 |                   0 |              0
         2 | BUY    |      5 |            100 |                   6 |              0
         2 | SELL   |      2 |             50 |                  11 |              0
         3 | SELL   |      5 |             80 |                   9 |              2
         4 | SELL   |      4 |            150 |                   4 |              7
    (5 rows)
    

इस तालिका के साथ, हम एक स्व-जुड़ना कर सकते हैं जहां प्रत्येक "खरीदें" रिकॉर्ड प्रत्येक भविष्य के "सेल" रिकॉर्ड से जुड़ा होता है। परिणाम इस तरह दिखेगा:

    SELECT buy.round, buy.shares, buy.profitpershare
          ,sell.round AS sellRound, sell.shares AS sellShares, sell.profitpershare AS sellProfitpershare
      FROM x buy
          ,x sell
      WHERE sell.round > buy.round
        AND buy.action = 'BUY'
        AND sell.action = 'SELL'

     round | shares | profitpershare | sellround | sellshares | sellprofitpershare
    -------+--------+----------------+-----------+------------+--------------------
         1 |      6 |            200 |         2 |          2 |                 50
         1 |      6 |            200 |         3 |          5 |                 80
         1 |      6 |            200 |         4 |          4 |                150
         2 |      5 |            100 |         3 |          5 |                 80
         2 |      5 |            100 |         4 |          4 |                150
    (5 rows)

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

   -- allocated sells 
   sell.previous_sells - buy.previous_sells

   -- shares yet to sell for this buy, if < 0 then 0
   GREATEST(buy.shares - (sell.previous_sells - buy.previous_sells), 0)

   -- number of sell shares that need to be skipped
   buy.previous_net_shares

डेविड को उनके सहायता




  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 पाठ खोज और जुड़ता है

  2. ADO . का उपयोग करके Oracle से कनेक्ट करना

  3. डेटाबेस सत्र संदर्भ में परिवर्तन पूल किए गए कनेक्शन के पुन:उपयोग के साथ बना रहता है

  4. .पैच_स्टोरेज

  5. मेरी एसक्यूएल स्क्रिप्ट कैसे निर्धारित कर सकती है कि यह एसक्लडेवलपर या एसक्लप्लस में चल रही है या नहीं?