FIFO匹配第一股买入首先卖sql

时间:2016-02-13 16:42:00

标签: sql sql-server common-table-expression fifo cursors

我的数据如下:

Stock buys and sells

我需要一个查询来将FIFO方法应用于Buys and Sells,所以我得到一个如下所示的表: FIFO Buys and Sells

我希望能够将第一次买入与第一次买入匹配,并在左边买入并在右边卖出。如果没有卖出,则应在右侧应用Null,如果没有买入,则应在左侧应用空值。经纪交易密钥可以用作交易发生的顺序。这是我迄今为止所尝试过的。任何帮助将不胜感激!

SELECT  a.ACCT_ID, a.Trade_Date_Key, a.Brokerage_Transaction_Key, a.Buy_Sell_Code, a.Principal_Amt, a.Security_Quantity
     , (a.Security_Quantity + b.Security_Quantity) CUMULATIVE_POSITION
     , a.SHARE_PRICE
     , (A.Principal_Amt + B.Principal_Amt) CUMULATIVE_VALUE
from #TRANSACTIONS_WITH_RANK a
     left join #TRANSACTIONS_WITH_RANK b 
     on a.acct_id = b.acct_id and a.rank = b.rank + 1
ORDER BY BROKERAGE_TRANSACTION_KEY

1 个答案:

答案 0 :(得分:0)

在你的问题中,你提到将第一次购买与第一次购买匹配,但你的示例输出似乎忽略了那一部分。以下是根据Acct_IDTrade_Date

将第一次购买与首次购买匹配的方法示例
SELECT buy.*, sell.*
FROM #TRANSACTIONS_WITH_RANK buy
    INNER JOIN (
        SELECT MIN(Trade_Date) Trade_Date
        FROM #TRANSACTIONS_WITH_RANK
        WHERE Buy_Sell_Code = 'B'
        GROUP BY Acct_ID
    ) TDateBuy
    ON buy.Trade_Date = TDateBuy.Trade_Date
    FULL OUTER JOIN #TRANSACTIONS_WITH_RANK sell
        INNER JOIN (
            SELECT MIN(Trade_Date) Trade_Date
            FROM #TRANSACTIONS_WITH_RANK
            WHERE Buy_Sell_Code = 'S'
            GROUP BY Acct_ID
        ) TDateSell
        ON sell.Trade_Date = TDateSell.Trade_Date
    ON buy.Acct_ID = sell.Acct_ID

编辑:看到OP的评论后,我更改了查询

SELECT 
    buy.Acct_ID, buy.Trade_Date, buy.Brokerage_Transaction_Key, buy.Buy_Sell_Code, buy.Principal_Amt, buy.Security_Quantity, 
    sell.Acct_ID, sell.Trade_Date, sell.Brokerage_Transaction_Key, sell.Buy_Sell_Code, sell.Principal_Amt, sell.Security_Quantity
FROM (
        SELECT wr.*, MIN(TransKey) TransKey -- This is the value of the Sell to be joined
        FROM #TRANSACTIONS_WITH_RANK wr
            LEFT OUTER JOIN (
                SELECT MIN(Brokerage_Transaction_Key) TransKey, Acct_ID
                FROM (
                        SELECT 
                            tr.*, 
                            (
                                SELECT MAX(Brokerage_Transaction_Key) --Purpose is to give outer query value to GROUP on
                                FROM #TRANSACTIONS_WITH_RANK 
                                WHERE Buy_Sell_Code = 'B' 
                                    AND Acct_ID = tr.Acct_ID
                                    AND Brokerage_Transaction_Key < tr.Brokerage_Transaction_Key
                            ) MaxLesserKey
                        FROM #TRANSACTIONS_WITH_RANK tr
                    ) data
                WHERE Buy_Sell_Code = 'S'
                GROUP BY Acct_ID, MaxLesserKey
            ) MinSell
            ON wr.Acct_ID = MinSell.Acct_ID
                AND wr.Brokerage_Transaction_Key < MinSell.TransKey
        WHERE Buy_Sell_Code = 'B'
        GROUP BY wr.Acct_ID, Trade_Date, Brokerage_Transaction_Key, Buy_Sell_Code, Principal_Amt, Security_Quantity
    ) buy
    FULL OUTER JOIN (
        SELECT wr.*, MIN(MinBuy.TransKey) TransKey -- This is the value of the Buy to be joined
        FROM #TRANSACTIONS_WITH_RANK wr
            LEFT OUTER JOIN (
                SELECT MIN(Brokerage_Transaction_Key) TransKey, Acct_ID
                FROM (
                        SELECT 
                            tr.*,
                            (
                                SELECT MAX(Brokerage_Transaction_Key) --Purpose is to give outer query a value to GROUP on
                                FROM #TRANSACTIONS_WITH_RANK
                                WHERE Buy_Sell_Code = 'S'
                                    AND Brokerage_Transaction_Key < tr.Brokerage_Transaction_Key
                            ) MaxLesserKey
                        FROM #TRANSACTIONS_WITH_RANK tr
                    ) data
                WHERE Buy_Sell_Code = 'B'
                GROUP BY Acct_ID, MaxLesserKey
            ) MinBuy
            ON wr.Acct_ID = MinBuy.Acct_ID
                AND wr.Brokerage_Transaction_Key < MinBuy.TransKey
        WHERE Buy_Sell_Code = 'S'
        GROUP BY wr.Acct_ID, Trade_Date, Brokerage_Transaction_Key, Buy_Sell_Code, Principal_Amt, Security_Quantity
    ) sell
    ON buy.TransKey = sell.Brokerage_Transaction_Key
        OR sell.TransKey = buy.Brokerage_Transaction_Key

基本上这样做是抓住所有买入及其匹配卖出Brokerage_Transaction_KeyTransKey)并执行FULL OUTER JOINNULL出买或卖出当没有相反的匹配交易时,对卖出的一组及其匹配的买Brokerage_Transaction_KeyTransKey)。 对于每组买入/卖出,TransKey是相对Brokerage_Transaction_Key的最小Buy_Sell_Code。这将为您提供特定Acct_ID的每组交易的首次卖出或首次卖出或首次卖出。 MaxLesserKey字段只是为TransKey查询提供GROUP上的值