[英]How i can optimize my ranking query in mysql?
針對每個訂閱 ID 為每個日期保存多條記錄。 有硬幣欄,所有訂閱者獲得的硬幣很少。 它基本上是一個獎勵系統。 我想獲得當前訂閱者的排名。 有 2 個表正在使用。
例如,如果用戶總共賺了 1000 個硬幣,它在用戶獎勵表中仍然是 1000,如果他在某處使用了 200 個硬幣,我在硬幣歷史表中添加一個條目。 所以目前他還剩下800個硬幣。 我將不得不找到當前硬幣的排名。
例如,我的用戶獎勵中有 5 條記錄存在於 3 個訂閱者 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 |
+-----------------+--------------+-------+
訂閱 ID 525252
有60
硬幣,989898 有10
硬幣, 454545
有50
硬幣。 但是,訂閱ID 525252
采用了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 = ?;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.