从表中获取用户的最高分

时间:2016-11-17 18:37:52

标签: mysql sql greatest-n-per-group

我有一种感觉这是一个非常简单的问题,但也许我现在正在做脑屁并且似乎无法弄清楚如何去做。

我有一个类似于下面的MySQL表结构

+---------------------------------------------------+
| id |     date     |  score  |  speed  |  user_id  |
+---------------------------------------------------+
|  1 |  2016-11-17  |  2      | 133291  |     17    |
|  2 |  2016-11-17  |  6      | 82247   |     17    |
|  3 |  2016-11-17  |  6      | 21852   |     17    |
|  4 |  2016-11-17  |  1      | 109338  |     17    |
|  5 |  2016-11-17  |  7      | 64762   |     61    |
|  6 |  2016-11-17  |  8      | 49434   |     61    |

现在我可以通过这样做获得特定用户的最佳表现

SELECT * 
FROM performance 
WHERE user_id = 17 AND date = '2016-11-17'
ORDER BY score desc,speed asc LIMIT 1

这应该返回ID = 3的行。现在我想要的是运行一个查询,以便能够为表中的每个唯一user_id返回1个这样的行。因此得到的结果将是这样的

+---------------------------------------------------+
| id |     date     |  score  |  speed  |  user_id  |
+---------------------------------------------------+
|  3 |  2016-11-17  |  6      | 21852   |     17    |
|  6 |  2016-11-17  |  8      | 49434   |     61    |

此外,我是否可以在同一查询中有另一个问题,该问题将通过相同的排序条件(得分desc,速度asc)进一步对此最终结果表进行排序。感谢

3 个答案:

答案 0 :(得分:3)

一种简单的方法使用相关子查询:

select p.* 
from performance p
where p.date = '2016-11-17' and
      p.id = (select p2.id
              from performance p2
              where p2.user_id = p.user_id and p2.date = p.date
              order by score desc, speed asc
              limit 1
             );

这应该能够利用performance(date, user_id, score, speed)上的索引。

答案 1 :(得分:2)

使用变量轻松模拟row_number() over (partition by Order by)

说明:

  1. 首先在子查询中创建两个变量。
  2. user_id排序,以便用户将@rn重置更改为1
  3. score desc,speed asc排序,以便每一行都有一个row_number,而您想要的那一行将有rn = 1
  4. @rn :=您为每行更改@rn
    • 如果您有新的user_id,则@rn设置为1
    • 否则@rn设置为@rn+1
  5. <强> SQL Fiddle Demo

    SELECT `id`, `date`, `score`, `speed`, `user_id`
    FROM (
            SELECT *,
                   @rn := if(@user_id = `user_id`, 
                             @rn + 1 , 
                             if(@user_id := `user_id`,1,1)
                            ) as rn           
            FROM Table1
            CROSS JOIN (SELECT @user_id := 0, @rn := 0) as param
            WHERE date = '2016-11-17' 
            ORDER BY `user_id`, `score` desc, `speed` asc
         ) T
    where T.rn =1      
    

    <强>输出

    enter image description here

答案 2 :(得分:0)

对于mysql

您可以尝试使用subselect中的double和

分组
  select * from    performance
  where (user_id, score,speed ) in (

            SELECT user_id, max_score, max(speed)
            FROM performance 
            WHERE (user_id, score) in (select user_id, max(score) max_score
                                       from performance 
                                       group by user_id)
            group by user_id, max_score
  );