对值求和,直到条件的下一次出现

Posted

技术标签:

【中文标题】对值求和,直到条件的下一次出现【英文标题】:Sum Values Till the Next Appearance of a Condition 【发布时间】:2019-12-29 02:29:07 【问题描述】:

感谢您的光临。

我有一张这样的桌子:

这就是我想要做的:按 id 隔离,我想根据条件总结 Val。 例如,对于 id=1,我想要 Val 的总和直到条件 A 首先出现,然后是第一个 A 和第二个 A 之间的另一个 Val 总和,以及第二个和第三个 A 之间的 Val 总和......总和当条件 = B 时的 Val 遵循相同的逻辑,但不应受 A 影响。最后,Val 的每个总和仅对相同的 id 求和。

我应该怎么做?我尝试了 group by 和 partition by,但无法获得理想的结果。理想的输出应该是图片中的 Sum 列。

非常感谢。

【问题讨论】:

SQL 表代表 无序 集。您的问题似乎需要在表格中进行排序,但没有一列明显指定它。 【参考方案1】:

假设有一列指定了排序,那么你可以做你想做的事。 SQL 表表示无序集。除非列指定排序,否则没有排序。

您似乎想为 As 和 Bs 定义组。您可以使用窗口函数来执行此操作。这有点奇怪,因为您需要不同的分组——case 表达式可以处理它。思路如下:

select t.*,
       (case when condition = 'A'
             then sum(val) over (partition by id, grp_a order by <ordering col>)
             when condition = 'B'
             then sum(val) over (partition by id order by <ordering col>)
        end) as calculation
from (select t.*,
             sum(case when condition = 'A' then 1 else 0 end) over (partition by id order by <ordering col> desc) as grp_a
      from t
     ) t;

【讨论】:

成功了,非常感谢!是的,抱歉我忘了提,这些行是按日期排序的。【参考方案2】:

你正在寻找这样的东西:

WITH somatory as (SELECT id, cond, v, 
SUM(v) OVER (PARTITION BY id ORDER BY id ROWS UNBOUNDED PRECEDING) as sumV
from foo),

conditional_somatory as (
select id, cond, v, sumV,
case when cond = 'A' then sumV end as somatoryA,
case when cond = 'B' then sumV end as somatoryB
from somatory
),

last_somatories as (
select id, cond, v, sumV,
SomatoryA,
max(coalesce(somatoryA,0)) over (partition by id order by id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) as lastSomatoryA,
SomatoryB,
max(coalesce(somatoryB,0)) over (partition by id order by id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) as lastSomatoryB
from conditional_somatory)

select id, cond, v,
case when cond = 'A' then sumV - lastSomatoryA
when cond = 'B' then sumV - lastSomatoryB 
end as somatory
from last_somatories

查看工作小提琴。

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=2b2d23b1421aa8fb45aa82ed8bad8b32

【讨论】:

以上是关于对值求和,直到条件的下一次出现的主要内容,如果未能解决你的问题,请参考以下文章

标记直到下一次出现数据

Oracle 窗口函数 - 检索元素直到下一次出现值

C#:获取窗口服务的下一次执行时间

如何暂停 Oracle Job 的下一次运行?

下一次构建后的下一个 JS 图像提供 404 个图像

调用`async for in`后如何获得异步生成器的下一次迭代