Reputation: 1781
The example table as below show.
+-------+------------+------+
| score | created | uid |
+-------+------------+------+
| 89 | 2017-08-01 | 101 |
| 69 | 2017-08-02 | 101 |
| 99 | 2017-08-03 | 101 |
| 79 | 2017-08-03 | 102 |
| 69 | 2017-08-04 | 102 |
| 90 | 2017-08-02 | 102 |
+-------+------------+------+
I want to query all user maximum score, so i try the below sql.
select uid, max(score) as max_score from minTable group by uid;
I got a result.
+------+-----------+
| uid | max_score |
+------+-----------+
| 101 | 99 |
| 102 | 90 |
+------+-----------+
For now, I expect to know what date created is with the maximum rows! I know i can use subquery to get it. like the below sql
select a.uid, a.score, a.created
from minTable a
INNER JOIN
(select uid, max(score) as max_score from minTable group by uid)b
ON a.uid=b.uid and a.score=b.max_score;
And then it's seems got the expect result.
+------+-------+------------+
| uid | score | created |
+------+-------+------------+
| 101 | 99 | 2017-08-03 |
| 102 | 90 | 2017-08-02 |
+------+-------+------------+
After insert more record with the below sql.
insert into minTable (uid, score, created) values (102, 90, "2017-08-01");
insert into minTable (uid, score, created) values (102, 90, "2017-08-05");
I try query with subquery again.
+------+-------+------------+
| uid | score | created |
+------+-------+------------+
| 101 | 99 | 2017-08-03 |
| 102 | 90 | 2017-08-02 |
| 102 | 90 | 2017-08-01 |
| 102 | 90 | 2017-08-05 |
+------+-------+------------+
It's more than one record with each uid, I know i can do group again ! like the below way.
SELECT c.uid, c.score, min(c.created) as min_created
FROM (
select a.uid, a.score, a.created
from minTable a
INNER JOIN
(select uid, max(score) as max_score from minTable group by uid)b
ON a.uid=b.uid and a.score=b.max_score)c GROUP BY c.uid, c.score;
Got the expect result:
+------+-------+-------------+
| uid | score | min_created |
+------+-------+-------------+
| 101 | 99 | 2017-08-03 |
| 102 | 90 | 2017-08-01 |
+------+-------+-------------+
I want to know is there any simple way to do this query ?
Upvotes: 2
Views: 91
Reputation: 33945
Here's a method (albeit one with certain vulnerabilities), but anyway I prefer yours...
SELECT *
FROM mintable
WHERE FIND_IN_SET(id,(SELECT GROUP_CONCAT(id ORDER BY score DESC,created) FROM mintable)) <= 2;
+----+-------+------------+------+
| id | score | created | uid |
+----+-------+------------+------+
| 3 | 99 | 2017-08-03 | 101 |
| 7 | 90 | 2017-08-01 | 102 |
+----+-------+------------+------+
Upvotes: 1
Reputation: 17655
You could do it by assigning a row number using a variable , but I prefer your solution.
drop table if exists mintable;
create table mintable(score int, created date, uid int);
insert into mintable values
( 89 , '2017-08-01' , 101),
( 69 , '2017-08-02' , 101),
( 99 , '2017-08-03' , 101),
( 79 , '2017-08-03' , 102),
( 69 , '2017-08-04' , 102),
( 90 , '2017-08-02' , 102),
( 90 , '2017-08-01' , 102),
( 90 , '2017-08-05' , 102);
select s.uid,s.created,s.score from
(
select m.uid,m.created,m.score,
if(m.uid <> @p ,@rn:=1,@rn:=@rn+1) rn ,
@p:=m.uid
from mintable m ,(select @rn:=0,@p:=0) r
order by m.uid,m.score desc,created
) s where s.rn = 1
Result
+------+------------+-------+
| uid | created | score |
+------+------------+-------+
| 101 | 2017-08-03 | 99 |
| 102 | 2017-08-01 | 90 |
+------+------------+-------+
2 rows in set (0.00 sec)
Upvotes: 1
Reputation: 5396
Yes, there it's an easiest way, just grouping by:
select uid, max(score) as max_score,min(c.created) as min_created
from minTable
group by uid,score;
Upvotes: -1