对值求和,直到条件的下一次出现
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
【讨论】:
以上是关于对值求和,直到条件的下一次出现的主要内容,如果未能解决你的问题,请参考以下文章