按列值的差异对 SQL 中的数据进行分组
Posted
技术标签:
【中文标题】按列值的差异对 SQL 中的数据进行分组【英文标题】:Grouping data in SQL by difference in column values 【发布时间】:2018-02-12 06:34:32 【问题描述】:我在 postgres 表的日志表中有以下数据:
-
logid => int(自动递增)
start_time => bigint(存储纪元值)
inserted_value => int
以下是存储在表中的数据(其中实际开始时间不是列,只是以UTC格式以24小时格式显示start_time值)
logid user_id start_time inserted_value start time actual
1 1 1518416562 15 12-Feb-2018 06:22:42
2 1 1518416622 8 12-Feb-2018 06:23:42
3 1 1518417342 9 12-Feb-2018 06:35:42
4 1 1518417402 12 12-Feb-2018 06:36:42
5 1 1518417462 18 12-Feb-2018 06:37:42
6 1 1518418757 6 12-Feb-2018 06:59:17
7 1 1518418808 11 12-Feb-2018 07:00:08
我想根据 start_time 的差异对值进行分组和求和
对于上述数据,应分三组计算总和:
user_id sum
1 15 + 8
1 9 + 12 + 18
1 6 + 11
因此,每组中的值有 1 分钟的差异。这个 1 可以被认为是任何 x 分钟的差异。
我也在尝试LAG
功能,但无法完全理解。我希望我能够解释我的问题。
【问题讨论】:
【参考方案1】:您可以使用普通的group by
来实现您想要的。只需使属于同一分钟的所有start_time
值相等。例如
select user_id, start_time/60, sum(inserted_value)
from log_table
group by user_id, start_time/60
我假设您的 start_time
列包含表示毫秒的整数,因此 /60
将正确地将它们截断为分钟。如果值是浮点数,则应使用floor(start_time/60)
。
如果您还想选择分组时的可读日期,可以将to_timestamp((start_time/60)*60)
添加到选择列表中。
【讨论】:
start_time 以毫秒为单位存储纪元值,表示自 1970 年 1 月 1 日以来经过的毫秒数 恐怕没那么简单。1518416562
是 2018-02-12T06:22:42
和 1518416622
是 2018-02-12T06:23:42
。我认为 06:22:42
和 06:23:42
必须组合在一起,但 06:22:42
和 06:23:43
不应该。
如果必须将 06:22:42 和 06:23:42 组合在一起,则跨度超过一分钟。通过传递性,06:23:42 和 06:24:42 也必须组合在一起,这会将所有时间归为一个组:-)
@dnswlt 编辑了我的问题,添加了 2 个日志条目以使问题更清晰
好的,现在我明白了!只要与前一个条目的差异不大于一分钟,您就希望对值求和。那么@SalmanA 的使用窗口函数的解决方案可能是要走的路。【参考方案2】:
您可以使用LAG
检查当前行是否比前一行多 60 秒,并在每次发生这种情况时设置group_changed
(虚拟列)。
在下一步中,对该列使用运行总和。这将创建一个group_number
,您可以使用它来对第三步中的结果进行分组。
WITH cte1 AS (
SELECT
testdata.*,
CASE WHEN start_time - LAG(start_time, 1, start_time) OVER (PARTITION BY user_id ORDER BY start_time) > 60 THEN 1 ELSE 0 END AS group_changed
FROM testdata
), cte2 AS (
SELECT
cte1.*,
SUM(group_changed) OVER (PARTITION BY user_id ORDER BY start_time) AS group_number
FROM cte1
)
SELECT user_id, SUM(inserted_value)
FROM cte2
GROUP BY user_id, group_number
SQL Fiddle
【讨论】:
以上是关于按列值的差异对 SQL 中的数据进行分组的主要内容,如果未能解决你的问题,请参考以下文章