+---------------+---------+
|Column Name |Type|+---------------+---------+
| stock_name | varchar ||operation| enum || operation_day | int || price | int |+---------------+---------+
(stock_name, operation_day) is the primarykey (combination of columns withuniquevalues) for this table.
The operationcolumnis an ENUM (category) oftype ('Sell', 'Buy')
Eachrowof this table indicates that the stock which has stock_name had an operationon the day operation_day with the price.
It is guaranteed that each'Sell'operationfor a stock has a corresponding 'Buy'operationin a previous day. It is also guaranteed that each'Buy'operationfor a stock has a corresponding 'Sell'operationin an upcoming day.
Write a solution to report the Capital gain/loss for each stock.
The Capital gain/loss of a stock is the total gain or loss after buying and selling the stock one or many times.
Example 1:Input:
Stocks table:+---------------+-----------+---------------+--------+| stock_name | operation | operation_day | price |+---------------+-----------+---------------+--------+| Leetcode | Buy |1|1000|| Corona Masks | Buy |2|10|| Leetcode | Sell |5|9000|| Handbags | Buy |17|30000|| Corona Masks | Sell |3|1010|| Corona Masks | Buy |4|1000|| Corona Masks | Sell |5|500|| Corona Masks | Buy |6|1000|| Handbags | Sell |29|7000|| Corona Masks | Sell |10|10000|+---------------+-----------+---------------+--------+Output:
+---------------+-------------------+| stock_name | capital_gain_loss |+---------------+-------------------+| Corona Masks |9500|| Leetcode |8000|| Handbags |-23000|+---------------+-------------------+Explanation:
Leetcode stock was bought at day 1for1000$ and was sold at day 5for9000$. Capital gain =9000-1000=8000$.Handbags stock was bought at day 17for30000$ and was sold at day 29for7000$. Capital loss =7000-30000=-23000$.Corona Masks stock was bought at day 1for10$ and was sold at day 3for1010$. It was bought again at day 4for1000$ and was sold at day 5for500$. At last, it was bought at day 6for1000$ and was sold at day 10for10000$. Capital gain/loss is the sum of capital gains/losses foreach('Buy'-->'Sell') operation =(1010-10)+(500-1000)+(10000-1000)=1000-500+9000=9500$.
We simulate the buy and sell operations for each stock in order of operation_day. For each stock, we match each ‘Sell’ with the earliest unmatched ‘Buy’ (FIFO), and sum the gain/loss for each pair. This can be done in SQL using window functions and self-joins.
WITH buys AS (
SELECT stock_name, price AS buy_price, ROW_NUMBER() OVER (PARTITION BY stock_name ORDERBY operation_day) AS rn
FROM Stocks
WHEREoperation='Buy'),
sells AS (
SELECT stock_name, price AS sell_price, ROW_NUMBER() OVER (PARTITION BY stock_name ORDERBY operation_day) AS rn
FROM Stocks
WHEREoperation='Sell')
SELECT b.stock_name, SUM(s.sell_price - b.buy_price) AS capital_gain_loss
FROM buys b
JOIN sells s ON b.stock_name = s.stock_name AND b.rn = s.rn
GROUPBY b.stock_name
ORDERBY b.stock_name;