有一个scores_score
表,其中包含以下列:
id, player_name, value, created_at
我必须获得N(100)个最佳分数,其中:
假设我有以下数据:
id player_name value date
1 A 400 2016-09-10
2 B 200 2016-09-12
3 C 400 2016-09-15
4 C 500 2016-09-14
5 B 100 2016-09-20
6 A 6000 2015-01-01
7 B 1200 2016-09-29
想要在2016-09-01和2016-09-20之间获得最佳分数。我应该得到:
id player_name value date
4 C 500 2016-09-14
1 A 400 2016-09-10
2 B 200 2016-09-12
这是我解决它的方法,但是在嵌套的SELECT中存在一个问题,因为它在日期范围内获取整体播放器的最佳分数。
SELECT b.*, a.*
FROM (SELECT player_name, max(value) AS max_value
FROM scores_score
GROUP BY player_name
ORDER BY max(value) DESC) a
INNER JOIN scores_score b ON a.player_name = b.player_name AND a.max_value = b.value
WHERE CAST(b.created_at AS DATE) >= %(date_border)s
ORDER BY b.value DESC
LIMIT 100
答案 0 :(得分:3)
select *
from (
select distinct on (player_name) *
from scores_score
where date between '2016-09-01' and '2016-09-20'
order by player_name, value desc
) s
order by value desc
limit 100
答案 1 :(得分:1)
这将起作用,并将为您提供预期的输出。使用row_number()
窗口函数标记日期之间每个玩家的最高分(rn = 1
),然后按value
降序排列结果集,最后将输出限制为最高100。
select
id, player_name, value, created_at
from (
select
id, player_name, value, created_at,
row_number() over (partition by player_name order by value desc, id) as rn
from scores_score
where created_at between '2016-09-01' and '2016-09-20'
) ranks
where rn = 1
order by value desc
limit 100
请注意,用于在id
函数内进行排序的附加列row_number
用于解析关系(即使它在分区内每行只分配一个值),这将涉及具有相同值的两行的同一玩家在给定日期内。这将获得较旧的记录,如果它们与created_at
日期不同,您会看到输出的差异: - )
答案 2 :(得分:0)
这个有点麻烦,但应该有用。首先选择日期范围内的玩家和值(a)。然后按球员(b)选择最高分数。然后加入id和日期(c):
SELECT c.id, c.player_name, c.value, c.date
FROM
scores_score c
INNER JOIN
(SELECT player_name, max(value)
FROM
(SELECT player_name, value
FROM scores_score
WHERE date BETWEEN '2016-09-01' AND '2016-09-20') a
GROUP BY player_name) b
ON c.player_name = b.player_name
AND c.value = b.value
ORDER BY value
LIMIT 100