簡體   English   中英

Select 最小行數,直到列的總和大於一個值

[英]Select minimal rows until sum of a column greater than a value

我在 Postgresql 有一個表(訂單),架構和數據是這樣的:

+----+---------+------+-------+------+--------+
| id | symbol  | qty  | price | side | status |
+----+---------+------+-------+------+--------+
| 1  | BTCUSDT | 0.02 | 6500  | SELL | NEW    | 
+----+---------+------+-------+------+--------+
| 2  | BTCUSDT | 1.00 | 6550  | SELL | NEW    |
+----+---------+------+-------+------+--------+
| 3  | BTCUSDT | 0.03 | 6600  | SELL | NEW    |
+----+---------+------+-------+------+--------+

我想要 select 行,其中邊是 SELL,狀態是 NEW,按價格升序排列,直到 sum(qty) 大於 0.5,所以結果應該是 select id 1 和 2

當我運行此查詢時:

SELECT * FROM (
       SELECT *, SUM(qty) OVER (ORDER BY price ASC) as total_qty FROM orders 
       WHERE symbol = 'BTCUSDT' AND side = 'SELL' AND status = 'NEW'
    ) AS o WHERE o.total_qty <= 0.5

它只返回第一行(id:1),我需要一個查詢返回 1 和 2

您需要保留兩個SUM 一個用於當前行,另一個用於上一行。 然后,過濾很容易。 例如:

select *
from (
  SELECT *, 
    SUM(qty) OVER (partition by side, status ORDER BY price ASC) as total_qty,
    SUM(qty) OVER (partition by side, status ORDER BY price ASC
      rows between unbounded preceding and 1 preceding) as prev_total_qty
  FROM orders 
  WHERE symbol = 'BTCUSDT' AND side = 'SELL' AND status = 'NEW'
) AS o 
WHERE coalesce(prev_total_qty, 0) <= 0.5

請參閱DB Fiddle上的運行示例。

您需要所有行,直到總和等於或超過0.5的行。
這意味着,如果您從要返回的最后一行的總和中減去qty ,則結果必須小於qty
從總和中減去qty並從WHERE子句中刪除等號:

SELECT o.id, o.symbol, o.qty, o.price, o.side, o.status 
FROM (
  SELECT *, SUM(qty) OVER (ORDER BY price ASC) - qty as total_qty 
  FROM orders 
  WHERE symbol = 'BTCUSDT' AND side = 'SELL' AND status = 'NEW'
) AS o 
WHERE o.total_qty < 0.5

請參閱演示
結果:

| id  | symbol  | qty  | price | side | status |
| --- | ------- | ---- | ----- | ---- | ------ |
| 1   | BTCUSDT | 0.02 | 6500  | SELL | NEW    |
| 2   | BTCUSDT | 1.00 | 6550  | SELL | NEW    |

你走在正確的軌道上。 問題是累積總和包括當前行。 因此,您的where子句在通過 0.5 時將其過濾掉。 簡單的解決方案是從當前行中減去該值:

SELECT *
FROM (SELECT o.*, SUM(qty) OVER (ORDER BY price ASC) as total_qty
      FROM orders o
      WHERE symbol = 'BTCUSDT' AND side = 'SELL' AND status = 'NEW'
     ) o
WHERE o.total_qty - o.qty <= 0.5;

您也可以像 Impaler 那樣使用 window 框架,但這會在第一行引入NULL值的問題。 您還可以像 forpas 一樣減去子查詢中的金額。 在所有情況下,想法都是一樣的:您需要在每行之前累積數量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM