Tôi biết đây là một câu hỏi cũ và sẽ không có ích cho áp phích gốc, nhưng tôi muốn bắt đầu câu hỏi này vì nó là một câu hỏi thú vị. Tôi đã không kiểm tra nó đủ, vì vậy tôi hy vọng điều này vẫn cần được sửa chữa và điều chỉnh. Nhưng tôi tin rằng cách tiếp cận là hợp pháp. Tôi không khuyên bạn nên sử dụng một truy vấn như thế này trong một sản phẩm vì nó sẽ khó duy trì hoặc khó hiểu (và tôi không tin rằng điều này thực sự có thể mở rộng). Bạn sẽ tốt hơn nhiều nếu tạo một số cấu trúc dữ liệu thay thế. Phải nói rằng, đây là những gì tôi đã chạy trong 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
Và kết quả:
round | net
-------+-----
1 | 780
2 | 420
(2 rows)
Để chia nó thành nhiều phần, tôi bắt đầu với tập dữ liệu này:
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)
Truy vấn trong mệnh đề "VỚI" thêm một số tổng đang chạy vào bảng.
- "before_net_shares" cho biết số lượng cổ phiếu có sẵn để bán trước kỷ lục hiện tại. Điều này cũng cho tôi biết tôi cần bỏ qua bao nhiêu cổ phiếu "BÁN" trước khi có thể bắt đầu phân bổ nó cho "MUA" này.
-
"before_sells" là tổng số lượt chia sẻ "SELL" gặp phải, do đó, sự khác biệt giữa hai "before_sells" cho biết số lượt chia sẻ 'SELL' được sử dụng trong thời gian đó.
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)
Với bảng này, chúng ta có thể tự tham gia trong đó mỗi bản ghi "MUA" được liên kết với mỗi bản ghi "BÁN" trong tương lai. Kết quả sẽ như thế này:
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)
Và sau đó là phần điên rồ cố gắng tính toán số lượng cổ phiếu có sẵn để bán theo thứ tự so với số lượng cổ phiếu chưa được bán để mua. Dưới đây là một số lưu ý để giúp làm theo điều đó. Các lệnh gọi "lớn nhất" với "0" chỉ nói rằng chúng ta không thể phân bổ bất kỳ cổ phiếu nào nếu chúng ta đang ở mức âm.
-- 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
Cảm ơn David vì hỗ trợ