简体   繁体   English

如何在 mysql 中优化我的排名查询?

[英]How i can optimize my ranking query in mysql?

Multiple records are being saved for each date against each subscription id.针对每个订阅 ID 为每个日期保存多条记录。 There is coins column, All subscriber gets few coins.有硬币栏,所有订阅者获得的硬币很少。 It is basically a rewarding system.它基本上是一个奖励系统。 I want to get the rank of current subscriber.我想获得当前订阅者的排名。 There are 2 tables that are being used.有 2 个表正在使用。

  1. user_rewards (which saves all the records with coins) user_rewards(用硬币保存所有记录)
  2. coins_history (if coins are used, then i add the used coins in coins history table) coins_history(如果使用了硬币,那么我将使用的硬币添加到硬币历史表中)

For example if user has earned total of 1000 coins, it remains 1000 in user reward table, and if he has used 200 coins somewhere, i add an entry in coins history table.例如,如果用户总共赚了 1000 个硬币,它在用户奖励表中仍然是 1000,如果他在某处使用了 200 个硬币,我在硬币历史表中添加一个条目。 So currently he has 800 coins left.所以目前他还剩下800个硬币。 I will have to find rank with current coins.我将不得不找到当前硬币的排名。

For example, I have 5 records exist in my user reward against 3 subscriber ids.例如,我的用户奖励中有 5 条记录存在于 3 个订阅者 ID 中。 I want to get the rank of one subscriber against his subscription_id.我想根据他的 subscription_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 |
+-----------------+--------------+-------+

The subscription ids 525252 has 60 coins, 989898 has 10 coins and 454545 has 50 coins.订阅 ID 52525260硬币,989898 有10硬币, 45454550硬币。 But subscription id 525252 has used 40 of his coins, 40 coins are added in coins history table.但是,订阅ID 525252采用了40他的硬币, 40硬币在硬币历史表添加。 So 454545 ranks first with 50 coins, 525252 ranks 2nd with 20 coins and 989898 ranks 3rd with 10 coins.因此, 45454550硬币排名第一, 52525220硬币排名第二, 98989810硬币排名第三。

So for getting rank of user.所以为了获得用户的排名。 I get sum of coins from user reward table, then minus it with coins history table against that subscription id.我从用户奖励表中获得硬币总和,然后根据该订阅 ID 用硬币历史记录表减去它。 Then find the rank against his current unused coins.然后根据他当前未使用的硬币找到排名。 Below is my query, Query took 34.0794 sec.以下是我的查询,查询耗时 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

Note: I have around 800000 records in one month, it will keep on increasing daily, So need to optimize my current query, I am using MySQL and PHP.注意:我在一个月内有大约 800000 条记录,它会每天增加,所以需要优化我当前的查询,我使用 MySQL 和 PHP。

You can calculate the total coins per subscriber using union all and group by .您可以使用union allgroup by来计算每个订阅者的总硬币数。 Then use window functions for the ranking:然后使用窗口函数进行排名:

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 = ?;
          

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM