sql >> データベース >  >> RDS >> Oracle

OracleSQLを使用した論理ネッティングを使用したロールアップクエリ

    これは古い質問で、元のポスターには役に立たないことはわかっていますが、興味深い質問だったので、これを試してみたかったのです。私はそれを十分にテストしなかったので、これはまだ修正して調整する必要があると思います。しかし、私はそのアプローチが正当であると信じています。このようなクエリを製品で使用することは、保守や理解が難しいためお勧めしません(そして、これが本当にスケーラブルであるとは思いません)。いくつかの代替データ構造を作成する方がはるかに良いでしょう。そうは言っても、これは私が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_net_shares"は、現在のレコードの前に販売できる株式数を示します。これにより、この「購入」への割り当てを開始する前にスキップする必要のある「販売」共有の数もわかります。
    • 「previous_sells」は、検出された「SELL」共有の数の現在のカウントであるため、2つの「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)
      

    このテーブルを使用して、各「BUY」レコードが各将来の「SELL」レコードに関連付けられる自己結合を実行できます。結果は次のようになります:

        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. Laravel5.3モデルの作成戻り値フィールドにはデフォルト値がありません

    2. OracleD2kFormsでPLSQLコードのパフォーマンスを調整またはテストする方法

    3. このSQLでは何を指していませんか?

    4. 致命的なエラー:キャッチされない例外'mysqli_sql_exception'とメッセージ'クエリ/プリペアドステートメントでインデックスが使用されていません'