我有一个名为Scores
的表,其中包含以下列:id
,player_id
,value1
,value2
,value3
和{{1 }}
该表格包含以下内容:
date
我正在尝试获取一个查询,该查询返回按“value1,value2,value3”中的值排序的每个玩家的最佳高分。 Value1是具有更高重要性,value2中等重要性和value3次要重要性的字段,例如:
+------+-----------+--------+--------+--------+------------+
| id | player_id | value1 | value2 | value3 | date |
+------+-----------+--------+--------+--------+------------+
| 1 | 1 | 10 | 0 | 0 | 2012-08-02 |
+------+-----------+--------+--------+--------+------------+
| 2 | 2 | 15 | 1 | 0 | 2012-08-03 |
+------+-----------+--------+--------+--------+------------+
| 3 | 3 | 9 | 0 | 0 | 2012-08-04 |
+------+-----------+--------+--------+--------+------------+
| 4 | 1 | 11 | 0 | 0 | 2012-08-05 |
+------+-----------+--------+--------+--------+------------+
| 5 | 2 | 16 | 2 | 0 | 2012-08-06 |
+------+-----------+--------+--------+--------+------------+
| 6 | 2 | 15 | 0 | 0 | 2012-08-07 |
+------+-----------+--------+--------+--------+------------+
我需要的查询的预期结果是:
value1 = 15 value1 = 15
value2 = 1 is greater than -> value2 = 0
value3 = 0 value3 = 1
我正在尝试 MAX , DISTINCT , GROUP BY 和子查询,但我没有得到正确的结果。基本上它是下一个查询,但选择每个“组”的第一行:
+------+-----------+--------+--------+--------+------------+
| id | player_id | value1 | value2 | value3 | date |
+------+-----------+--------+--------+--------+------------+
| 5 | 2 | 16 | 2 | 0 | 2012-08-06 |
+------+-----------+--------+--------+--------+------------+
| 4 | 1 | 11 | 0 | 0 | 2012-08-05 |
+------+-----------+--------+--------+--------+------------+
| 3 | 3 | 9 | 0 | 0 | 2012-08-04 |
+------+-----------+--------+--------+--------+------------+
------ 编辑1 -------
eggyal的回答运作正常,但也许,表现不太好。我需要针对大型数据库对其解决方案进行基准测试,以检查响应时间。
我有一个想法(和可能的解决方案)。解决方案包括添加新的布尔列,其中说明该得分是否是该玩家的最佳得分。这样我需要检查当我将新分数添加到数据库中时,新分数是否优于该分区的最佳旧分数,如果是,我需要在旧的最佳分数中将该标记标记为假,并且在新的分数。这为我提供了一种直接检索每个玩家最佳得分的方法(简单查询,如SELECT id, player_id, value1, value2, value3
FROM scores
ORDER BY value1 DESC, value2 DESC, value3 DESC
)。
------ 编辑2 -------
weicap的回答是最快的解决方案。我不知道为什么,但他的查询比 eggyal的查询快两倍。
------ 编辑3 ------- 我错了,如果查询先前被缓存,weicap的查询会更快,如果不是查询需要十秒或更长时间。在变化中,weicap的答案总是需要300-400ms而不是80.000行。
答案 0 :(得分:5)
对于每个value
,您都可以获得groupwise maximum:
SELECT * FROM Scores NATURAL JOIN (
SELECT player_id, value1, value2, MAX(value3) value3 FROM Scores NATURAL JOIN (
SELECT player_id, value1, MAX(value2) value2 FROM Scores NATURAL JOIN (
SELECT player_id, MAX(value1) value1 FROM Scores
GROUP BY player_id) t
GROUP BY player_id) t
GROUP BY player_id) t
ORDER BY value1 DESC, value2 DESC, value3 DESC
在sqlfiddle上查看。
答案 1 :(得分:3)
你可以试试这个
SELECT player_id,
(SELECT value1
FROM Scores b where a.player_id=b.player_id ORDER BY value1 DESC, value2 DESC, value3 DESC limit 1) as value1,
(SELECT value2
FROM Scores b where a.player_id=b.player_id ORDER BY value1 DESC, value2 DESC, value3 DESC limit 1) as value2,
(SELECT value3
FROM Scores b where a.player_id=b.player_id ORDER BY value1 DESC, value2 DESC, value3 DESC limit 1) as value3
FROM Scores a GROUP BY player_id order by value1 DESC, value2 DESC, value3 DESC
或类似
SELECT * FROM Scores a
where id =(SELECT id
FROM Scores b where a.player_id=b.player_id ORDER BY value1 DESC, value2 DESC, value3 DESC limit 1)
GROUP BY player_id order by value1 DESC, value2 DESC, value3 DESC
答案 2 :(得分:2)
尝试在(player_id, value1, value2, value3)
上添加索引,然后在此查询中添加:
SELECT
s.*
FROM
Scores AS s
JOIN
( SELECT DISTINCT
player_id
FROM
Scores
) AS p
ON s.id =
( SELECT
id
FROM
Scores AS b
WHERE
b.player_id = p.player_id
ORDER BY
value1 DESC, value2 DESC, value3 DESC
LIMIT 1
)
ORDER BY
s.value1 DESC, s.value2 DESC, s.value3 DESC ;
答案 3 :(得分:0)
你的实际得分是:1000,1510,900等......你明白了吗? 它就像十进制数字,其中单个数字的位置很重要。 您可以将3个值转换为单个值以进行分组,您可以在运行中(在查询中右侧)进行估计,也可以预先计算它(在将其写入表之前)。
答案 4 :(得分:0)
您使用的是哪种语言(SQL除外)?如果SQL可以对它进行排序,那将是最简单的,但我不认为这是可能的。如果您使用的是PHP,那么您可以将它放在for循环中,为数组添加索引,例如'bestScore',然后单独检查每个分数,如下所示:
//Extract Data Here
for($outI=0;$outI<count($scores);$outI++){
$scores[$outI]['bestScore'] = 0;
for($innI=0;$innI<=3;$innI++){
if ($scores[$outI]['value' . $innI+1] > $scores[$outI]['bestScore'])
$scores[$outI]['bestScore'] = $scores[$outI]['value' . $innI+1];
}
echo 'The best score for ' . $scores[$outI]['player_id'] . ' was ' . $scores[$outI]['bestScore'] . '.<br />';
}
如果按预期工作,则应列出每位玩家的最佳分数。
答案 5 :(得分:0)
假设你的最大疼痛可以是16,试试这个,
Select Scores.* from Scores, (SELECT player_id,max(17*17*value1+17*value2+value3)
as max_score FROM Scores group by player_id)t where
(17*17*value1+17*value2+value3) = t.max_score and Scores.player_id=t.player_id
答案 6 :(得分:-2)
SELECT * FROM (
SELECT id, player_id, value1, value2, value3, `date`
FROM scores
ORDER BY value1 DESC, value2 DESC, value3 DESC
) x
GROUP BY player_id
order by value1 DESC, value2 DESC, value3 DESC