我有一张看起来像这样的桌子......
user_id, match_id, points_won
1 14 10
1 8 12
1 12 80
2 8 10
3 14 20
3 2 25
我想写一个MYSQL脚本,它可以回退用户在一场比赛中赢得的最多分数,并在结果中包含match_id - 换句话说......
user_id, match_id, max_points_won
1 12 80
2 8 10
3 2 25
当然,如果我不需要match_id,我可以做......
select user_id, max(points_won)
from table
group by user_id
但是一旦我将match_id添加到"选择" " group by"我每场比赛都有一行,如果我只将match_id添加到"选择" (而不是""组)然后它不能正确地与points_won相关联。
理想情况下,我不想做以下事情,因为它感觉不是特别安全(例如,如果用户在多场比赛中获得相同数量的分数)......
SELECT t.user_id, max(t.points_won) max_points_won
, (select t2.match_id
from table t2
where t2.user_id = t.user_id
and t2.points_won = max_points_won) as 'match_of_points_maximum'
FROM table t
GROUP BY t.user_id
这个问题还有更优雅的选择吗?
答案 0 :(得分:2)
这比在MySQL中需要的更难。一种方法有点像黑客,但它在大多数情况下都有效。这是group_concat()
/ substring_index()
诀窍:
select user_id, max(points_won),
substring_index(group_concat(match_id order by points_won desc), ',', 1)
from table
group by user_id;
group_concat()
将所有match_id
连接在一起,按降序排列。然后substring_index()
接受第一个。
两个重要的警告:
group_concat()
使用内部缓冲区,其长度(默认情况下)为1,024个字符。可以更改此默认长度。答案 1 :(得分:1)
您可以使用查询:
select user_id, max(points_won)
from table
group by user_id
作为派生表。将其加入原始表可以获得您想要的结果:
select t1.user_id, t1.match_id, t2.max_points_won
from table as t1
join (
select user_id, max(points_won) as max_points_won
from table
group by user_id
) as t2 on t1.user_id = t2.user_id and t1.points_won = t2.max_points_won
答案 2 :(得分:0)
编辑:仅适用于postgresql,sql-server,oracle
您可以使用row_number:
SELECT USER_ID, MATCH_ID, POINTS_WON
FROM
(
SELECT user_id, match_id, points_won, row_number() over (partition by user_id order by points_won desc) rn
from table
) q
where q.rn = 1
对于类似的功能,请查看Gordon Linoff的答案或article。
在您的示例中,您按照每个用户对结果集进行分区,然后通过points_won desc命令首先获得最高获胜点。
答案 3 :(得分:0)
我认为您可以通过在内部查询中添加限制1来优化查询。
SELECT t.user_id, max(t.points_won) max_points_won
, (select t2.match_id
from table t2
where t2.user_id = t.user_id
and t2.points_won = max_points_won limit 1) as 'match_of_points_maximum'
FROM table t
GROUP BY t.user_id