有这样一个表,表里记录的是用户获得金币的记录表,每一条记录都详细的说明了这一条记录的金币是怎么得到的(或者用掉的),表结构大概如下:
id,user_id,count(得到 /消费的金币数量),change_type(得到 /消费的类型),create_time
现在有个需求:得到用户每一条记录创建时的剩余金币数,
得到的结果大概为:
id | user_id | count | change_type | create_time | remain |
---|---|---|---|---|---|
1 | 1 | 10 | 1 | 2020-10-10 | 10 |
2 | 1 | -2 | 2 | 2020-10-10 | 8 |
3 | 1 | 15 | 3 | 2020-10-10 | 23 |
4 | 1 | -14 | 4 | 2020-10-10 | 9 |
其实就是要这个 remain 字段。
1
MrGoooo OP | id | user_id | count | change_type | create_time | remain |
| ---- | ----| ---- | ----| ---- | ----| | 1 | 1 | 10 | 1 | 2020-10-10 | 10 | | 2 | 1 | -2 | 2 | 2020-10-10 | 8 | | 3 | 1 | 15 | 3 | 2020-10-10 | 23 | | 4 | 1 |-14 | 4 | 2020-10-10 | 9 | |
2
gtchan13579 2021-09-02 09:45:30 +08:00
remain 这个字段我认为不应该跟这个记录一起存储吧
何况这个字段其实不需要存储,查询一下 userid 然后统计一下 count 就出来了吧 |
3
MrGoooo OP @gtchan13579 就是现在表里没有存 remain,需要把这个字段查出来,想对这个查询过程优化
|
4
shyrock 2021-09-02 09:52:52 +08:00
remain 要存储当时的剩余金币值?你这相当于找回历史记录啊。写个脚本对每个用户追溯一次记录呗。
|
5
AngryPanda 2021-09-02 09:52:57 +08:00 1
SELECT id, score, (SELECT SUM(score) FROM score WHERE id <= s.id) as remain FROM `score` s
|
6
zhaokun 2021-09-02 09:53:43 +08:00 1
SQL 都没有,何来优化之说??
|
7
sadfQED2 2021-09-02 10:04:58 +08:00 via Android
建表语录,select 语录你发出来啊,不然优化空气啊
|
10
MrGoooo OP @AngryPanda 我就是你这么写的,不过要加上用户 id 判断,
SELECT id, count, (SELECT SUM(count) FROM coin_record WHERE id <= s.id and user_id = '1') as remain FROM `coin_record ` s where user_id = '1' |
11
0o0o0o0 2021-09-02 11:33:27 +08:00
sum(count) over ( order by id ) as remain
|
12
Egfly 2021-09-02 11:36:56 +08:00
|
13
Egfly 2021-09-02 11:39:45 +08:00 1
我觉得还是加一个 remain 字段,然后写个脚本维护一下历史数据比较好。适当的冗余一些字段,可以省很多事情
|
14
c6h6benzene 2021-09-02 12:58:30 +08:00 via iPhone
就是按行算 sum 吧。rows unbounded preceding
|
15
IvanLi127 2021-09-02 13:46:57 +08:00
如果能把余额也记录在表里的话,每次变化时查出上次余额后计算成当前余额一起写入,应该就不需要想怎么优化了。毕竟数据写入后不太可能变化,挺适合冗余的。
|
16
justfindu 2021-09-02 13:54:11 +08:00
你这个得每行进行重新计算. 一条 sql 看起来是没啥戏的
|
17
dodosh 2021-09-02 14:14:13 +08:00
开窗函数。
|
18
Jface 2021-09-02 14:17:54 +08:00
感觉开窗函数可以搞定。sum(count ) over(partition by user_id order by create_time ) as remain
|
19
sakasaka 2021-09-02 14:19:14 +08:00
可取方案不是优化 SQL,而是优化存储结构,这样的 SQL 写起来蠢蠢的
|
20
brookepe 2021-09-02 16:07:41 +08:00
```
select *, (uremain - IFNULL(sremain, 0)) as remain from ( select coin_record.*, users.remain as uremain, (select sum(count) from coin_record cr1 where cr1.id > coin_record.id) sremain from coin_record left join users on users.id = coin_record.user_id ) as coin_record ``` |
21
MrGoooo OP 了解一下开窗函数,explain 后发现会导致 filesort,好像用不了索引,不知道为啥
|