首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Oracle SQL的具有一些逻辑网格化的汇总查询

使用Oracle SQL的具有一些逻辑网格化的汇总查询
EN

Stack Overflow用户
提问于 2009-12-02 01:16:06
回答 1查看 546关注 0票数 1

我有一个类似下面的表"AuctionResults“

代码语言:javascript
复制
Auction  Action    Shares  ProfitperShare   
------------------------------------------- 
Round1   BUY        6      200    
Round2   BUY        5      100   
Round2   SELL      -2      50   
Round3   SELL      -5      80

现在我需要在“先到先净额”的基础上,在接下来的几轮中通过买入来汇总每次拍卖的结果。

所以在Round1中,我买了6股,然后在Round2中卖出了2股,在Round3中卖出了"4“股,总净利润为6* 200-2 * 50-4 * 80 = 780

在Round2,我买了5股,卖出了Round3的"1“(因为之前的"4”属于Round1),净利润为5* 100-1 * 80 = 420

...so生成的输出应如下所示:

代码语言:javascript
复制
Auction   NetProfit
------------------
Round1    780    
Round2    420   

我们是否可以仅使用Oracle SQL(10g)而不使用PL-SQL来完成此操作

提前感谢

EN

回答 1

Stack Overflow用户

发布于 2012-01-12 11:22:31

我知道这是一个老生常谈的问题,对最初的海报没有什么用处,但我想尝试一下,因为这是一个有趣的问题。我没有对它进行足够的测试,所以我认为这仍然需要纠正和调整。但我相信这种方法是合法的。我不建议在产品中使用这样的查询,因为它很难维护或理解(而且我不相信这是真正可伸缩的)。你最好创建一些替代的数据结构。话虽如此,以下是我在Postgresql 9.1中运行的内容:

代码语言:javascript
复制
    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

结果是:

代码语言:javascript
复制
     round | net
    -------+-----
         1 | 780
         2 | 420
    (2 rows)

为了将其分成几个部分,我从这个数据集开始:

代码语言:javascript
复制
    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“表示在当前记录之前有多少股票可供出售。这也告诉我在开始分配给这个'BUY'.
  • "previous_sells“之前,我需要跳过多少”卖出“股票,这是遇到的”卖出“股票数量的连续计数,所以两个"previous_sells”之间的差值表示在这段时间内使用的“卖出”股票数量。

轮|行动|股|盈利股| previous_net_shares | previous_sells -------+--------+--------+----------------+---------------------+---------------- 1|购买|6| 200 |0|0 2|购买|5| 100 |6|0 2|出售|2| 50 | 11 |0 3|出售|5| 80 |92 4|销售|4| 150 |4|7 (5行)

有了这个表,我们可以做一个自连接,其中每个“买入”记录都与每个未来的“卖出”记录相关联。结果将如下所示:

代码语言:javascript
复制
    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“的”最大“调用只是说,如果我们是负的,我们就不能分配任何份额。

代码语言:javascript
复制
   -- 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

感谢大卫的assistance

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1827619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档