No Loops solution using SQL
Recently came across a problem posed here. Basically, it is a test for a programmer to see if she can come up with a solution using a set-based, non-procedural approach to the problem. Two set-based solutions are already presented at the link. Here I present another solution.
What is the problem?
For the sake of completeness, here is a copy of text of the problem, verbatim, from the above link.
You have a table of trading days (with no gaps) and close prices for a stock.
CREATE TABLE stock (
trading_date DATE UNIQUE,
price FLOAT
);
Find the highest and lowest profits (or losses) you could have made if you bought the stock at one close price and sold it at another close price, i.e. a total of exactly two transactions.
You cannot sell a stock before it has been purchased. Your solution can allow buying and selling on the same trading_date (i.e. profit or loss of $0 is always, by definition, an available option); however, for some bonus points, you may write a more general solution for this problem that requires you to hold the stock for at least N days.
The problem also provides some synthetic data which I am copying here again for reproducibility purposes.
INSERT INTO stock VALUES
('2015-06-01', 41),
('2015-06-02', 43),
('2015-06-03', 47),
('2015-06-04', 42),
('2015-06-05', 45),
('2015-06-08', 39),
('2015-06-09', 38),
('2015-06-10', 41);
Given this dataset, the biggest profit you can make is $6, and the smallest profit is -$9 (i.e. a loss of $9).
My no loop solution
As stated before, the source link provides you with 2 solutions. Here is my solution to the problem:
;with CTE1(price, max_following_price, min_following_price) as
(
select price
, max(price) over(order by trading_date asc rows BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
, min(price) over(order by trading_date asc rows BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
from stock
),
CTE2 as
(
select max_following_price-price as greatest_potential_profit
, min_following_price - price as smallest_potential_profit
from CTE1
)
select MAX(greatest_potential_profit) as highest_profit
, MIN(smallest_potential_profit) as lowest_profit
from CTE2
Comments