【问题标题】:How to calculate a running total that is a distinct sum of values如何计算作为不同值总和的运行总计
【发布时间】:2017-09-01 22:34:11
【问题描述】:

考虑这个数据集:

id       site_id type_id value   date
-------  ------- ------- ------- -------------------
1        1       1       50      2017-08-09 06:49:47
2        1       2       48      2017-08-10 08:19:49
3        1       1       52      2017-08-11 06:15:00
4        1       1       45      2017-08-12 10:39:47
5        1       2       40      2017-08-14 10:33:00
6        2       1       30      2017-08-09 07:25:32
7        2       2       32      2017-08-12 04:11:05
8        3       1       80      2017-08-09 19:55:12
9        3       2       75      2017-08-13 02:54:47
10       2       1       25      2017-08-15 10:00:05 

我想构造一个查询,按类型返回每个日期的运行总计。我可以使用窗口函数接近,但我只希望将每个站点的最新值相加为运行总数(一个简单的窗口函数将不起作用,因为它将 all 值相加到一个日期--不仅仅是每个站点的最后一个值)。所以我想它可以更好地描述为一个运行不同的总数?

我正在寻找的结果是这样的:

type_id date                sum
------- ------------------- -------
1       2017-08-09 06:49:47 50
1       2017-08-09 07:25:32 80
1       2017-08-09 19:55:12 160
1       2017-08-11 06:15:00 162
1       2017-08-12 10:39:47 155
1       2017-08-15 10:00:05 150
2       2017-08-10 08:19:49 48
2       2017-08-12 04:11:05 80
2       2017-08-13 02:54:47 155
2       2017-08-14 10:33:00 147

这里的关键是总和不是运行总和。它应该只是每个站点在每个日期按类型的最新值的总和。我想我可以通过浏览上面提供的结果集来帮助解释它。对于我的解释,我将按时间顺序遍历原始数据并尝试解释预期的结果。

结果的第一行从 2017-08-09 06:49:47 开始,按时间顺序,只有一个类型 1 的记录,它是 50,所以这是我们 2017-08 的总和-09 06:49:47。

结果的第二行是 2017-08-09 07:25:32,此时我们有 2 个唯一站点,其值为 type_id = 1。它们的值为 50 和 30,因此总和是 80。

结果的第三行出现在 2017-08-09 19:55:12,现在我们有 3 个站点,其值为 type_id = 1. 50 + 30 + 80 = 160。

第四行是有趣的地方。在 2017-08-11 06:15:00 有 4 条 type_id = 1 的记录,但其中 2 条用于同一站点。我只对每个站点的最新值感兴趣,所以我想总结的值是:30 + 80 + 52 导致 162

第 5 行与第 4 行相似,因为 site_id:1、type_id:1 的值再次更改,现在为 45。这导致 type_id:1 的最新值在 2017 年 8 月 12 日 10:39: 47 现在是:30 + 80 + 45 = 155。

当我们考虑到 2017-08-15 10:00:05 时,查看第 6 行也很有趣,站点 2 具有 type_id 1 的新值,这给我们:80 + 45 + 25 = 150 表示 2017-08-15 10:00:05。

【问题讨论】:

  • 我相信你需要按 type_id 分区
  • 类似这样的:select type_id , date , sum(value) over (partition by type_id order by date) from table order by type_id, date
  • 我可以理解您的前三个总和值 (50,80,160) 的值来自哪里,但不确定为什么/如何第四行是 162?
  • type_id 1 只有 3 个唯一的 site_id。当您只想对每种类型的每个 site_id 的最新值求和时,为什么您的预期结果会有 5 行 type_id 1?
  • @FuzzyTree,我想要每次变化的总和,这样我就可以在历史上绘制图表。

标签: sql postgresql


【解决方案1】:

您可以通过在窗口框架中包含ORDER BY 子句来获得累计总数(运行总数)。

select
  type_id,
  date,
  sum(value) over (partition by type_id order by date) as sum
from your_table;

ORDER BY 之所以有效是因为

默认成帧选项为RANGE UNBOUNDED PRECEDING,与RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW相同。

【讨论】:

  • 感谢@Andy-Carlson,但我并不追求总和。我只想要每个站点的最新值的总和,按 type_id 分组。我会尽量让我的问题更清楚。
【解决方案2】:
SELECT      type_id,
            date,
            SUM(value) OVER (PARTITION BY type_id ORDER BY type_id, date) - (SUM(value) OVER (PARTITION BY type_id, site_id ORDER BY type_id, date) - value) AS sum
FROM        your_table
ORDER BY    type_id,
            date

【讨论】:

  • 这真是太聪明了!如果我们只有一个站点对一种类型有多个编号,则效果很好。我在我的数据集 (2017-08-15 10:00:05) 中添加了另一行,这会导致站点 2 的类型 1 值发生变化。这会导致您的建议有点麻烦,因为它只处理当前站点逐行。你有解决这个问题的想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 2019-06-09
  • 2023-03-23
  • 1970-01-01
  • 2018-03-13
  • 2013-04-17
相关资源
最近更新 更多