我有以下SQL表,用于跟踪用户在特定时间点的分数。用户每天可以获得多个分数。
+-------+------------+-------+-----+
| user | date | score | ... |
+-------+------------+-------+-----+
| bob | 2014-04-19 | 100 | ... |
| mary | 2014-04-19 | 100 | ... |
| alice | 2014-04-20 | 100 | ... |
| bob | 2014-04-20 | 110 | ... |
| bob | 2014-04-20 | 125 | ... |
| mary | 2014-04-20 | 105 | ... |
| bob | 2014-04-21 | 115 | ... |
+-------+------------+-------+-----+
鉴于特定用户(让我们说bob
),如何生成每个用户得分的报告,但只使用每天提交的最高得分?< / strong>(获得分数最高的特定行也很重要,而不仅仅是最高分)
SELECT * FROM `user_score` WHERE `user` = 'bob' GROUP BY `date`
是我建立的基本查询。它产生以下结果集:
+-------+------------+-------+-----+
| user | date | score | ... |
+-------+------------+-------+-----+
| bob | 2014-04-19 | 100 | ... |
| bob | 2014-04-20 | 110 | ... |
| bob | 2014-04-21 | 115 | ... |
+-------+------------+-------+-----+
bob
125
的{{1}}得分较高。我试过用2014-04-20
MAX(score)
返回当天的最高分,但不是得分最高的行。该行上的其他列值很重要,
SELECT *, MAX(score) FROM `user_score` WHERE `user` = 'bob' GROUP BY `date`
最后,我试过
+-------+------------+-------+-----+------------+
| user | date | score | ... | max(score) |
+-------+------------+-------+-----+------------+
| bob | 2014-04-19 | 100 | ... | 100 |
| bob | 2014-04-20 | 110 | ... | 125 |
| bob | 2014-04-21 | 115 | ... | 110 |
+-------+------------+-------+-----+------------+
但这会导致SELECT *, MAX(score) FROM `user_score` WHERE `user` = 'bob' AND score = MAX(score) GROUP BY `date`
无效使用。
编辑:
SQLFiddle:http://sqlfiddle.com/#!2/ee6a2
答案 0 :(得分:4)
如果您想要所有字段,MySQL中最简单(也是最快)的方法是使用not exists
:
SELECT *
FROM `user_score` us
WHERE `user` = 'bob' AND
NOT EXISTS (SELECT 1
FROM user_score us2
WHERE us2.`user` = us.`user` AND
us2.date = us.date AND
us2.score > us.score
);
这似乎是一种奇怪的方法。并且,我承认它是。它正在做的非常简单:“从user_score
获取Bob的所有行,其中没有更高的分数(对于Bob)”。这相当于获得最高分的行。使用user_score(name, score)
上的索引,这可能是执行所需操作的最有效方式。
答案 1 :(得分:2)
您可以使用JOIN
:
SELECT a.*
FROM `user_score` as a
INNER JOIN (SELECT `user`, `date`, MAX(score) MaxScore
FROM `user_score`
GROUP BY `user`, `date`) as b
ON a.`user` = b.`user`
AND a.`date` = b.`date`
AND a.score = b.MaxScore
WHERE a.`user` = 'bob'
答案 2 :(得分:0)
一种选择是使用内联视图和JOIN操作。如果给定日期的多个行具有“高分”值,则此查询将返回所有行。 (如果(user,date,score)
是唯一的,那么这不是问题。)
例如:
SELECT t.user
, t.date
, t.score
, t.`...`
FROM user_score t
JOIN ( SELECT d.user
, d.date
, MAX(s.score) AS score
FROM user_score d
WHERE d.user = 'bob'
GROUP BY d.user, d.date
) s
ON s.user = t.user
AND s.date = t.date
AND s.score = t.score