SQL 负值求和直到满足条件(看到正值),然后重新开始求和

SQL sum of negative values until condition (positive value is seen) is met, then restart the summation

我想获得负行值的总和,直到出现正值(这里是下面 table 中的列更改)。 在列中出现另一个负值后,总和应再次开始累积负行值,直到出现另一个正值,依此类推。 鉴于以下 table:

+─────+─────────+─────────────────────────+
| id  | change  | start_time              |
+─────+─────────+─────────────────────────+
| B   | -7.4    | 2022-05-21 11:59:54.0   |
| A   | -0.8    | 2022-05-21 22:48:47.0   |
| A   | -61.5   | 2022-05-22 09:25:22.0   |
| B   | -5.3    | 2022-05-22 11:32:14.0   |
| A   | -0.3    | 2022-05-22 12:18:49.0   |
| B   | -0.1    | 2022-05-22 12:44:05.0   |
| B   | -0.5    | 2022-05-22 12:55:38.0   |
| B   | -7.2    | 2022-05-22 13:10:20.0   |
| B   | 0.0     | 2022-05-22 13:55:04.0   |
| B   | 34.8    | 2022-05-22 13:55:54.0   |
| A   | 0.0     | 2022-05-22 15:31:47.0   |
| A   | -0.1    | 2022-05-22 15:57:19.0   |
| A   | 0.0     | 2022-05-22 15:58:17.0   |
| A   | -0.1    | 2022-05-22 17:51:38.0   |
| A   | 8.1     | 2022-05-22 17:55:01.0   |
| A   | -1.9    | 2022-05-22 17:57:26.0   |
| A   | 0.0     | 2022-05-22 18:06:03.0   |
| A   | 10.1    | 2022-05-22 18:06:08.0   |
| A   | -3.0    | 2022-05-22 20:34:26.0   |
+─────+─────────+─────────────────────────+

期望的结果应显示按 id 排序的每个总和的总负值:

+─────+─────────+
| id  | change  |
+─────+─────────+
| B   | -20.5   |
| A   | -62.8   |
| A   | -1.9    |
| A   | -3      |
+─────+─────────+

到目前为止,在看到第一个正值后,我只设法生成了 运行ning 个正值和负值。由于 B 的最后一个值为正,因此总和为 Null。 A 的第一个总和显示 5.19 总结所有(正负)值直到结束。但是,在检测到下一个正值之前,总和应该只 运行,并且应该只对负值求和。

+─────+────────────────────+
| id  | total_neg_change   |
+─────+────────────────────+
| B   | null               |
| A   | 5.199999999999999  |
| A   | -3.0               |
+─────+────────────────────+

此输出是通过 运行以下代码实现的:

SELECT id, total_neg_change
FROM(
SELECT
    id,
    change,
    SUM(change) OVER(PARTITION BY id ORDER BY start_time ASC ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ) AS total_neg_change
FROM test_table)
WHERE  change > 0

我假设“无限跟随”创造了累计和。我怎样才能改变它以获得上面我想要的结果?

这是一个缺口和岛屿问题,其中每个岛屿都是通过具有相同的 id 以及连续的负数来定义的。这是一种方法:

WITH cte AS (
    SELECT *, SUM(change > 0) OVER (PARTITION BY id ORDER BY start_time) grp
    FROM yourTable
)

SELECT id, SUM(change) AS total_neg_change
FROM cte
WHERE change < 0
GROUP BY id, grp
ORDER BY MIN(start_time);