1

我有一个名为的表,Scores其中包含列:idplayer_idvalue1、和。value2value3date

该表具有以下内容:

+------+-----------+--------+--------+--------+------------+
|  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,value2,value3”中的值排序的每个玩家的最佳高分。value1 为重要性较高的字段,value2 为中等重要性,value3 为次要的字段,例如:

value1 = 15                              value1 = 15
value2 = 1       is greater than ->      value2 = 0
value3 = 0                               value3 = 1

我需要的查询的预期结果是:

+------+-----------+--------+--------+--------+------------+
|  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 |
+------+-----------+--------+--------+--------+------------+

我正在尝试使用MAXDISTINCTGROUP BY和子查询,但我没有得到正确的结果。基本上它是下一个查询,但选择每个“组”的第一行:

SELECT id, player_id, value1, value2, value3
   FROM scores
   ORDER BY value1 DESC, value2 DESC, value3 DESC

------编辑 1 --------

eggyal 的回答效果很好,但也许性能不太好。我需要将他的解决方案与大型数据库进行基准测试,以检查响应时间。

我有一个想法(和可能的解决方案)。该解决方案包括添加新的布尔列,该列表示该分数是否是该玩家的最佳分数。这样,当我将新分数添加到数据库中时,我需要检查新分数是否优于该玩家的最佳旧分数,如果是我需要在旧的最佳分数中将标志标记为假,在新分数。这为我提供了一种直接检索每个玩家的最佳分数的方法(简单查询,如SELECT ... FROM .... ORDER BY)。

------编辑 2 --------

weicap 的回答是最快的解决方案。我不知道为什么,但他的查询比eggyal 的查询快两倍。

------ EDIT 3 -------- 我错了,如果之前缓存了查询,weicap 的查询会更快,如果不是,查询需要十秒或更长时间。相反,weicap 的回答总是需要 300-400 毫秒来处理 80.000 行。

4

7 回答 7

5

对于每个value,您可以获得分组最大值

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上查看。

于 2012-08-24T09:45:47.830 回答
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
于 2012-08-24T10:22:54.823 回答
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 ; 
于 2012-08-26T11:00:39.297 回答
0

你的实际分数是:1000、1510、900 等等……你明白了吗?就像十进制数字一样,单个数字的位置很重要。您可以将 3 个值转换为单个值以按其分组,并且可以即时估计它(在查询中),也可以预先计算它(在将其写入表之前)。

于 2012-08-24T09:31:46.913 回答
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 />';
}

如果它按预期工作,它应该列出每个玩家的最佳分数。

于 2012-08-24T09:38:53.093 回答
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
于 2012-08-24T10:04:11.120 回答
-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
于 2012-08-24T09:51:44.527 回答