Mysql 我如何改进查询,使玩家的排名仍然正确,即使有些玩家已经有一段时间没有玩了?
我试图根据月份和年份跟踪排行榜中某个玩家的排名变化。由于有一些玩家在某个特定时间内不玩游戏,他们的排名在这段时间内可能会较低 可以创建该表的简化版本:Mysql 我如何改进查询,使玩家的排名仍然正确,即使有些玩家已经有一段时间没有玩了?,mysql,Mysql,我试图根据月份和年份跟踪排行榜中某个玩家的排名变化。由于有一些玩家在某个特定时间内不玩游戏,他们的排名在这段时间内可能会较低 可以创建该表的简化版本: create table rating (player_id Integer(20) , game_id integer(20), start_date_time date, rating int (10) ) INSERT INTO rating (player_id, game_id,start_date_time,rating) V
create table rating
(player_id Integer(20) ,
game_id integer(20),
start_date_time date,
rating int (10)
)
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (1, 1,'2019-01-02',1250);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (1, 2,'2019-01-03',2230);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (1, 3,'2019-02-04',3362);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (1, 4,'2019-02-05',1578);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (2, 5,'2019-01-03',2269);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (2, 6,'2019-01-05',3641);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (2, 7,'2019-02-07',1548);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (2, 8,'2019-02-09',1100);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (3, 9,'2019-01-03',4690);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (3, 10,'2019-01-05',3258);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (3, 11,'2019-01-07',1520);
INSERT INTO rating (player_id, game_id,start_date_time,rating) VALUES (3, 12,'2019-01-09',3652);
我使用的查询如下:
select q1.rating_rank, q1.rating, q1.month,q1.year from (
SELECT player_id,month(start_date_time) as month, year(start_date_time) as year, round(avg(rating),2) as rating, count(*) as games_palyed,
rank() over(
partition by year(start_date_time),month(start_date_time)
order by avg(rating) desc ) as rating_rank
FROM rating
group by player_id,month(start_date_time), year(start_date_time)
having rating is not null) as q1
where player_id=1
我得到的结果是:
rating_rank rating month year
3 1740.00 1 2019
1 2470.00 2 2019
但是第三个盖伊德=3在他们当中显然更好,但因为他没有参加2月份的比赛,所以第一个家伙可以排名第一。
在这种情况下,我仍然希望第三名在排行榜上排名第一。我该如何解决这个问题
我想也许我可以用一个日期前15天,日期后15天的期限来代替确切的月份。但我不确定到底该怎么做
谢谢。这需要时间,但我认为您可以通过此查询完成以下任务: 首先,您必须在可能的数据和播放器之间生成所有组合: 这将给出以下日期:
WITH recursive mnths as (
select date_add(min(start_date_time),interval -DAY(min(start_date_time))+1 DAY) as mnth ,
date_add(max(start_date_time),interval -DAY(max(start_date_time))+1 DAY) as maxmnth from rating
UNION ALL -- start date begining of next month
SELECT DATE_ADD(mnth, INTERVAL +1 MONTH) , maxmnth
FROM mnths WHERE
mnth < maxmnth
)
然后,除了所涉及的计算之外,您还需要获得当前期间的评级值。这将通过此子查询完成:
(
SELECT
round(avg(rating),2) as rating
from
rating
where start_date_time < mnths.mnth and player_id = P.player_id
group by player_id,month(start_date_time), year(start_date_time)
having round(avg(rating),2) is not null
order by year(start_date_time) desc, month(start_date_time) desc
limit 1 ) as PrevRating,
将所有内容绑定在一起,最终将得到以下结果:
WITH recursive mnths as (
select date_add(min(start_date_time),interval -DAY(min(start_date_time))+1 DAY) as mnth ,
date_add(max(start_date_time),interval -DAY(max(start_date_time))+1 DAY) as maxmnth from rating
UNION ALL -- start date begining of next month
SELECT DATE_ADD(mnth, INTERVAL +1 MONTH) , maxmnth
FROM mnths WHERE
mnth < maxmnth
)
select q1.rating_rank, q1.rating, q1.month,q1.year from (
select AUX.player_id, AUX.month, AUX.year, CASE WHEN AUX.rating IS NULL THEN case WHEN AUX.PrevRating IS NULL THEN 0 ELSE AUX.PrevRating END ELSE AUX.rating END as rating,
AUX.games_palyed,
rank() over(
partition by AUX.month, AUX.year
order by CASE WHEN AUX.rating IS NULL THEN case WHEN AUX.PrevRating IS NULL THEN 0 ELSE AUX.PrevRating END ELSE AUX.rating END desc ) as rating_rank
FROM(
select
P.player_id,
MONTH(mnths.mnth) as month,
YEAR(mnths.mnth) as year,
(
SELECT
round(avg(rating),2) as rating
from
rating
where start_date_time < mnths.mnth and player_id = P.player_id
group by player_id,month(start_date_time), year(start_date_time)
having round(avg(rating),2) is not null
order by year(start_date_time) desc, month(start_date_time) desc
limit 1 ) as PrevRating,
V.rating rating,
case when V.games_palyed IS NULL THEN 0 ELSE V.games_palyed END as games_palyed
from mnths
cross join (Select distinct player_id from rating) as P
LEFT JOIN
(SELECT
player_id,
month(start_date_time) as month,
year(start_date_time) as year,
round(avg(rating),2) as rating,
count(*) as games_palyed
from
rating as R
group by player_id,month(start_date_time), year(start_date_time)
having rating is not null
) V On YEAR(mnths.mnth) = V.year and MONTH(mnths.mnth) = V.month and P.player_id = V.player_id
) as AUX
) as q1
where q1.player_id=1
您可以查看结果,这需要时间,但我认为您可以通过此查询完成以下任务: 首先,您必须在可能的数据和播放器之间生成所有组合: 这将给出以下日期:
WITH recursive mnths as (
select date_add(min(start_date_time),interval -DAY(min(start_date_time))+1 DAY) as mnth ,
date_add(max(start_date_time),interval -DAY(max(start_date_time))+1 DAY) as maxmnth from rating
UNION ALL -- start date begining of next month
SELECT DATE_ADD(mnth, INTERVAL +1 MONTH) , maxmnth
FROM mnths WHERE
mnth < maxmnth
)
然后,除了所涉及的计算之外,您还需要获得当前期间的评级值。这将通过此子查询完成:
(
SELECT
round(avg(rating),2) as rating
from
rating
where start_date_time < mnths.mnth and player_id = P.player_id
group by player_id,month(start_date_time), year(start_date_time)
having round(avg(rating),2) is not null
order by year(start_date_time) desc, month(start_date_time) desc
limit 1 ) as PrevRating,
将所有内容绑定在一起,最终将得到以下结果:
WITH recursive mnths as (
select date_add(min(start_date_time),interval -DAY(min(start_date_time))+1 DAY) as mnth ,
date_add(max(start_date_time),interval -DAY(max(start_date_time))+1 DAY) as maxmnth from rating
UNION ALL -- start date begining of next month
SELECT DATE_ADD(mnth, INTERVAL +1 MONTH) , maxmnth
FROM mnths WHERE
mnth < maxmnth
)
select q1.rating_rank, q1.rating, q1.month,q1.year from (
select AUX.player_id, AUX.month, AUX.year, CASE WHEN AUX.rating IS NULL THEN case WHEN AUX.PrevRating IS NULL THEN 0 ELSE AUX.PrevRating END ELSE AUX.rating END as rating,
AUX.games_palyed,
rank() over(
partition by AUX.month, AUX.year
order by CASE WHEN AUX.rating IS NULL THEN case WHEN AUX.PrevRating IS NULL THEN 0 ELSE AUX.PrevRating END ELSE AUX.rating END desc ) as rating_rank
FROM(
select
P.player_id,
MONTH(mnths.mnth) as month,
YEAR(mnths.mnth) as year,
(
SELECT
round(avg(rating),2) as rating
from
rating
where start_date_time < mnths.mnth and player_id = P.player_id
group by player_id,month(start_date_time), year(start_date_time)
having round(avg(rating),2) is not null
order by year(start_date_time) desc, month(start_date_time) desc
limit 1 ) as PrevRating,
V.rating rating,
case when V.games_palyed IS NULL THEN 0 ELSE V.games_palyed END as games_palyed
from mnths
cross join (Select distinct player_id from rating) as P
LEFT JOIN
(SELECT
player_id,
month(start_date_time) as month,
year(start_date_time) as year,
round(avg(rating),2) as rating,
count(*) as games_palyed
from
rating as R
group by player_id,month(start_date_time), year(start_date_time)
having rating is not null
) V On YEAR(mnths.mnth) = V.year and MONTH(mnths.mnth) = V.month and P.player_id = V.player_id
) as AUX
) as q1
where q1.player_id=1
你可以使用结果没有int20这样的东西。幸运的是,括号中的数字几乎完全没有意义。你能告诉我们期望的结果是什么样的吗?没有int20这样的东西。幸运的是,括号中的数字几乎完全没有意义。你能告诉我们期望的结果是什么样的吗?