Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

kueri Rollup dengan beberapa jaring logis menggunakan Oracle SQL

Saya tahu ini adalah pertanyaan lama dan tidak akan berguna untuk poster aslinya, tetapi saya ingin mencoba ini karena ini adalah pertanyaan yang menarik. Saya tidak cukup mengujinya, jadi saya berharap ini masih perlu diperbaiki dan disetel. Tapi saya percaya pendekatan itu sah. Saya tidak akan merekomendasikan menggunakan kueri seperti ini dalam suatu produk karena akan sulit untuk dipertahankan atau dipahami (dan saya tidak percaya ini benar-benar terukur). Anda akan jauh lebih baik membuat beberapa struktur data alternatif. Karena itu, inilah yang saya jalankan di 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

Dan hasilnya:

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

Untuk memecahnya menjadi beberapa bagian, saya mulai dengan kumpulan data ini:

    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)

Kueri dalam klausa "DENGAN" menambahkan beberapa total yang berjalan ke tabel.

  • "previous_net_shares" menunjukkan berapa banyak saham yang tersedia untuk dijual sebelum rekor saat ini. Ini juga memberi tahu saya berapa banyak saham 'JUAL' yang harus saya lewati sebelum saya dapat mulai mengalokasikannya ke 'BELI' ini.
  • "previous_sells" adalah hitungan berjalan dari jumlah saham "JUAL" yang ditemukan, jadi perbedaan antara dua "previous_sells" menunjukkan jumlah saham 'JUAL' yang digunakan pada waktu itu.

     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)
    

Dengan tabel ini, kita dapat melakukan self-join di mana setiap record "BUY" dikaitkan dengan setiap record "SELL" yang akan datang. Hasilnya akan terlihat seperti ini:

    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)

Dan kemudian muncul bagian gila yang mencoba menghitung jumlah saham yang tersedia untuk dijual dalam pesanan vs jumlah saham yang belum terjual untuk dibeli. Berikut adalah beberapa catatan untuk membantu mengikutinya. Panggilan "terbesar" dengan "0" hanya mengatakan bahwa kami tidak dapat mengalokasikan bagian apa pun jika kami berada di posisi negatif.

   -- 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

Terima kasih kepada David untuk bantuan




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. cara menemukan semua indeks dan kolomnya untuk tabel, tampilan, dan sinonim di oracle

  2. ORA-01795:jumlah maksimum ekspresi dalam daftar adalah 1000 , cara membagi string

  3. Apakah mungkin menggunakan pengembalian dalam prosedur tersimpan?

  4. Oracle ERROR:ORA-00900:pernyataan SQL tidak valid

  5. cx_Oracle dengan otentikasi Windows