我正在尝试根据月份和年份跟踪排行榜中玩家的排名变化。由于某些玩家在某些时间内不玩游戏,因此在此期间他们的排名可能会降低。
可以创建表格的简化版本:
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
但是第三个人(id = 3)在他们当中显然更好,但是因为他没有参加二月,所以第一个人可以排名第一。 在这种情况下,我仍然希望第三名成为排行榜上的第一名。我该如何解决?
我想也许我可以使用日期前15天和日期后15天的时间段,而不是确切的月份。但是我不确定该怎么做?
谢谢。
答案 0 :(得分:0)
这花了一些时间,但我想您可以通过以下查询来完成:
首先,您必须在可能的数据和播放器之间生成所有组合:
这将给出日期:
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 * from mnths
cross join (Select distinct player_id from rating) as P
然后,除了涉及计算之外,您还需要获取直到当前期间的评级值。这将通过以下子查询完成:
(
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,
这将使您不仅可以使用当前排名,还可以使用不存在时的上一个排名。
order by CASE WHEN AUX.rating IS NULL THEN case WHEN AUX.PrevRating IS NULL THEN
将所有内容绑定在一起,您将得到以下结果:
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
您可以查看结果here