mysql - 如何在 mysql 中优化我的排名查询?
问题描述
针对每个订阅 ID 为每个日期保存多条记录。有硬币栏,所有订阅者获得少量硬币。它基本上是一个奖励系统。我想获得当前订阅者的排名。有 2 个表正在使用中。
- user_rewards(用硬币保存所有记录)
- coin_history (如果使用硬币,那么我将使用过的硬币添加到硬币历史表中)
例如,如果用户总共获得了 1000 个硬币,它在用户奖励表中仍然是 1000,如果他在某处使用了 200 个硬币,我在硬币历史表中添加一个条目。所以目前他还剩下800个硬币。我将不得不找到当前硬币的排名。
例如,我的用户奖励中有 5 条记录存在于 3 个订阅者 ID 中。我想根据他的订阅 ID 获得一个订阅者的排名。
+-----------------+--------------+-------+
| subscription_id | date_awarded | coins |
+-----------------+--------------+-------+
| 525252 | 2020-09-11 | 10 |
| 454545 | 2020-09-11 | 20 |
| 989898 | 2020-09-11 | 10 |
| 525252 | 2020-09-10 | 50 |
| 454545 | 2020-09-10 | 30 |
+-----------------+--------------+-------+
订阅id525252
有60
币,989898有10
币,454545
有50
币。但是订阅 id525252
已经使用40
了他的硬币,40
硬币被添加到硬币历史表中。所以硬币454545
排名第一,50
硬币525252
排名第二,20
硬币989898
排名第三10
。
所以为了获得用户的排名。我从用户奖励表中获得硬币总和,然后用硬币历史表减去该订阅 ID。然后根据他当前未使用的硬币找到排名。下面是我的查询,查询耗时 34.0794 秒。
SELECT COUNT(*)+1 AS aboveRank
FROM
(
SELECT subscription_id
FROM user_rewards
GROUP BY subscription_id
HAVING SUM(coins) >
(Select (SELECT IFNULL(sum(coins), 0)
FROM user_rewards
WHERE subscription_id = 525252) -
(SELECT IFNULL(sum(coins), 0) as coins
FROM `coins_history`
where subscription_id = 525252) as z
)
) t
注意:我在一个月内有大约 800000 条记录,并且每天都会不断增加,所以需要优化我当前的查询,我正在使用 MySQL 和 PHP。
解决方案
union all
您可以使用和计算每个订阅者的总硬币数group by
。然后使用窗口函数进行排名:
select c.*
from (select subscription_id, sum(coins) as coins,
rank() over (order by coins desc) as seqnum
from ((select subscription_id, - sum(coins) as coins
from user_rewards ur
group by subscription_id
) union all
(select subscription_id, sum(coins)
from coins_history ch
group by subscription_id
)
) c
group by subscription_id
) c
where subscription_id = ?;
推荐阅读
- scala - 如何禁用 Akka WebSocket 服务器上的消息缓冲?
- c# - ASP.net Core中主机和服务器的区别和关系
- vba - 仅匹配对象名称的一部分
- bash - Bash - 以 CIDR 表示法转换网络掩码?
- c# - ASP.NET Core 2.0 - 提供没有扩展名的文件
- javascript - Promise 执行器中的 `resolve` 和 `reject` 函数
- angular - mat-table 中没有数据
- c++ - 小于 int 的数据的字段顺序保证
- shell - Shell-无法生成脚本的日志输出
- javascript - React - textDecoration:'none'不删除链接中的下划线