gpt4 book ai didi

mysql - 如何做滚动求和,每一行需要包括前几行的总和

转载 作者:可可西里 更新时间:2023-11-01 08:35:20 25 4
gpt4 key购买 nike

我有表 [访问]。当 order_number 为空时,我需要获取按 user_id 分组的行和 visit_duration_seconds 的总和,例如,对于用户 [2875636],我将得到:61+151+33+13。每行应包含其前几行的总和。
请引用下方预期结果中的 RESULT 列

user_id   starttime           visit_duration_seconds  order_number
2875636 2013-01-16 18:03:50 61
2875636 2013-01-16 18:08:18 151
2875636 2013-01-16 18:15:43 33
2875636 2013-01-16 18:16:37 13
2875636 2013-01-16 18:18:01 2011 10177888
2875636 2013-01-16 18:24:35 1172 10177884
2875636 2013-01-16 18:32:03 4731
2875636 2013-01-16 18:33:27 407
2875636 2013-01-16 18:37:29 74
2875636 2013-01-16 18:48:55 80
2875636 2013-01-16 19:05:00 1955
2875636 2013-01-16 19:14:12 326
2875636 2013-01-16 19:23:39 972
2875636 2013-01-16 19:33:05 5440
2875636 2013-01-16 19:35:48 43
2875636 2013-01-16 19:41:10 66
2875636 2013-01-16 19:42:03 100
2875636 2013-01-16 19:42:12 2414 10177940
2875636 2013-01-16 19:49:05 432 10177925
2875636 2013-01-16 19:50:19 183
2875636 2013-01-16 19:52:46 2061
2875636 2013-01-16 19:52:53 400
2875636 2013-01-16 20:00:47 338
2875636 2013-01-16 20:08:58 216
2875636 2013-01-16 20:14:21 58
2875636 2013-01-16 20:14:26 196
2875636 2013-01-16 20:19:14 2189
2875636 2013-01-16 20:21:29 424
2875636 2013-01-16 20:24:42 999
2875636 2013-01-16 21:01:39 1810
2875636 2013-01-16 21:02:54 525
2875636 2013-01-16 21:10:06 27
2875636 2013-01-16 21:12:08 282
2875636 2013-01-16 21:51:02 6
2875636 2013-01-16 22:18:34 173
2875636 2013-01-16 23:02:58 318
2875636 2013-01-16 23:45:37 207
3018868 2013-01-16 16:01:45 18
3018868 2013-01-16 16:16:45 39
3018868 2013-01-16 16:22:55 656
3018868 2013-01-16 16:25:54 1852
3018868 2013-01-16 16:29:23 688
3018868 2013-01-16 16:47:26 2258 10177846
3018868 2013-01-16 16:57:41 572
3018868 2013-01-16 17:06:47 1431
3018868 2013-01-16 17:18:32 29
3018868 2013-01-16 17:21:57 45
3018868 2013-01-16 17:29:23 16
3018868 2013-01-16 17:36:47 490

预期结果

user_id starttime           visit_duration_seconds  order_number        RESULT
2875636 2013-01-16 18:03:50 61 61
2875636 2013-01-16 18:08:18 151 212
2875636 2013-01-16 18:15:43 33 245
2875636 2013-01-16 18:16:37 13 258
2875636 2013-01-16 18:18:01 2011 10177888 0
2875636 2013-01-16 18:24:35 1172 10177884 0
2875636 2013-01-16 18:32:03 4731 4731
2875636 2013-01-16 18:33:27 407 5138
2875636 2013-01-16 18:37:29 74 5212
2875636 2013-01-16 18:48:55 80 ...
2875636 2013-01-16 19:05:00 1955 ...
2875636 2013-01-16 19:14:12 326 ...
2875636 2013-01-16 19:23:39 972
2875636 2013-01-16 19:33:05 5440
2875636 2013-01-16 19:35:48 43
2875636 2013-01-16 19:41:10 66
2875636 2013-01-16 19:42:03 100
2875636 2013-01-16 19:42:12 2414 10177940
2875636 2013-01-16 19:49:05 432 10177925
2875636 2013-01-16 19:50:19 183
2875636 2013-01-16 19:52:46 2061
2875636 2013-01-16 19:52:53 400
2875636 2013-01-16 20:00:47 338
2875636 2013-01-16 20:08:58 216
2875636 2013-01-16 20:14:21 58
2875636 2013-01-16 20:14:26 196
2875636 2013-01-16 20:19:14 2189
2875636 2013-01-16 20:21:29 424
2875636 2013-01-16 20:24:42 999
2875636 2013-01-16 21:01:39 1810
2875636 2013-01-16 21:02:54 525
2875636 2013-01-16 21:10:06 27
2875636 2013-01-16 21:12:08 282
2875636 2013-01-16 21:51:02 6
2875636 2013-01-16 22:18:34 173
2875636 2013-01-16 23:02:58 318
2875636 2013-01-16 23:45:37 207
3018868 2013-01-16 16:01:45 18
3018868 2013-01-16 16:16:45 39
3018868 2013-01-16 16:22:55 656
3018868 2013-01-16 16:25:54 1852
3018868 2013-01-16 16:29:23 688
3018868 2013-01-16 16:47:26 2258 10177846
3018868 2013-01-16 16:57:41 572
3018868 2013-01-16 17:06:47 1431
3018868 2013-01-16 17:18:32 29
3018868 2013-01-16 17:21:57 45
3018868 2013-01-16 17:29:23 16
3018868 2013-01-16 17:36:47 490

最佳答案

您可以使用 MySQL 用户变量来模拟分析函数。 (还有一些其他方法,例如使用半连接或使用相关子查询。如果您认为它们更合适,我也可以为这些方法提供解决方案。)

要模拟“运行总计”分析函数,请尝试如下操作:

SELECT t.user_id
, t.starttime
, t.order_number
, IF(t.order_number IS NOT NULL,
@tot_dur := 0,
@tot_dur := @tot_dur + t.visit_duration_seconds) AS tot_dur
FROM visit t
JOIN (SELECT @tot_dur := 0) d
ORDER BY t.user_id, t.start_time

这里的“技巧”是使用 IF 函数来测试 order_number 是否为 null。当它为空时,我们将持续时间值添加到变量,否则,我们将变量设置为零。

我们使用内联 View (别名为d,以确保将@tot_dur 变量初始化为零。

注意:像这样使用 MySQL 用户变量时要小心。在上面的 SELECT 语句中,SELECT 列表中的变量赋值发生在 ORDER BY 之后,因此我们可以获得确定性行为。


该查询不处理 user_id 中的“中断”。为此,我们将需要上一行中的 user_id 值。我们可以将其保存在另一个用户变量中。操作顺序是确定的,我们需要注意在覆盖前一行的 user_id 之前进行累加。

我们要么需要对列重新排序,以便 user_id 出现在 tot_dur 之后(或者包括 user_id 列的第二个副本)

SELECT t.user_id
, t.starttime
, t.order_number
, IF(t.order_number IS NULL,
@tot_dur := IF(@prev_user_id = t.user_id,@tot_dur,0) + t.visit_duration_seconds,
@tot_dur := 0
) AS tot_dur
, @prev_user_id := t.user_id AS prev_user_id
FROM visit t
JOIN (SELECT @tot_dur := 0, @prev_user_id := NULL) d
ORDER BY t.user_id, t.start_time

user_idprev_user_id 列中返回的值是相同的。可以删除该“额外”列,或者可以通过将查询(作为内联 View )包装在另一个查询中来重新排序列,尽管这会以性能成本为代价:

SELECT v.user_id
, v.starttime
, v.order_number
, v.tot_dur
FROM (SELECT t.starttime
, t.order_number
, IF(t.order_number IS NULL,
@tot_dur := IF(@prev_user_id = t.user_id,@tot_dur,0) + t.visit_duration_seconds,
@tot_dur := 0
) AS tot_dur
, @prev_user_id := t.user_id AS user_id
FROM visit t
JOIN (SELECT @tot_dur := 0, @prev_user_id := NULL) d
ORDER BY t.user_id, t.start_time
) v

该查询表明 MySQL 可以返回指定的结果集。但为了获得最佳性能,我们只想在内联 View (别名为 v)中运行查询,并在客户端处理列的重新排序(将 user_id 列放在首位)一边,当行被检索时。

其他两种常见方法是使用半连接和使用相关子查询,尽管这些方法在处理大型集合时可能会占用更多资源。

关于mysql - 如何做滚动求和,每一行需要包括前几行的总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14596107/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com