使用 SQL 创建 2 个带有条件的累积和“墨盒”

Posted

技术标签:

【中文标题】使用 SQL 创建 2 个带有条件的累积和“墨盒”【英文标题】:Creating 2 "cartridges" of cumulative sum with conditions using SQL 【发布时间】:2020-10-25 09:31:28 【问题描述】:

我需要根据值类型创建2个累积和,例如:

我有 2 种类型的进货单位的值:A 和 B。我也有出货单位的记录。

如果我们有足够的“A”型库存,则应从 A 型中取出,如果没有,则应从 B 型中取出。所以基本上我需要创建“A 库存”和“B 库存”列下图,代表当前每种类型的余额。

我尝试使用累积和,但我遇到了条件问题...有没有办法在不使用循环的情况下编写此查询? (垂直数据库)

下表中的 A_stock 和 B_stock 是我需要创建的最终结果

ID  Type    In      OUT     A stock B stock  Order_id
1   A       100     0       100     0        1
1   B       50      0       100     50       2
1   A       100     0       200     50       3
1   -       0       -200    0       50       4
1   -       0       -10     0       40       5
1   B       50      0       0       90       6
1   A       40      0       40      90       7
1   -       0      -20      20      90       8
2   A       30      0       30      0        1
2   B       20      0       30      20       2
2   A       10      0       40      20       3
2   -       0       -20     20      20       4

【问题讨论】:

您的问题似乎表明您的行是有序的。但是,SQL 表代表无序 数据集。除非您明确有一个带有排序的列,否则没有排序。 正如@GMB 指出的那样,您需要一个排序列开始。但是,其次 - 由于以下结果取决于之前发生的任何事情(1. 运行总和;2. 基于先前运行总和和余额的结果的决定),您将需要一个递归查询。而RECURSIVE WITH 子句在 Vertica 中不存在(还没有?)。解决方法是在WITH 子句中编写尽可能多的公用表表达式,因为您期望迭代是必要的。这可能会变得丑陋。 @marcothesane,是的,你当然是对的,要明确的是,我确实有办法对结果进行排序(在示例中添加了排序列)不幸的是我认为你是对的,我没有没有递归查询就没有办法做到这一点...... 【参考方案1】:

你可以使用窗口函数——但你需要一个定义行顺序的列,我假设ordering_id

select t.*,
    sum(case when type = 'A' then in + out else 0 end) over(partition by id order by ordering_id) a_stock,
    sum(case when type = 'B' then in + out else 0 end) over(partition by id order by ordering_id) b_stock
from mytable t

这假设您想要以每id 为基础的股票;如果不是这样,只需从over() 子句中删除partition 子句。

【讨论】:

您没有考虑type 列中带有NULL 的行——那些从库存中拿走某些东西并且开始出现决策问题的行,@GMT ...

以上是关于使用 SQL 创建 2 个带有条件的累积和“墨盒”的主要内容,如果未能解决你的问题,请参考以下文章

如何组合 2 个 SQL 查询并检索累积计数?

Oracle SQL - 基于分组和条件运行求和

基于条件的累积和,但条件结束后会重置

创建带有条件的 SQL 视图

SQL查询带有条件的最新值

如何在 LINQ 中计算累积和?