MySQL:获取给定日期的每个玩家的最终得分

时间:2015-11-11 18:18:25

标签: php mysql

我有一张桌子,根据日期存储每位玩家的得分。玩家可以在完成游戏的同一天保存多个分数。日期2015-10-01的示例数据是:

id     player_id     score        score_date
------------------------------------------------------
1      100           3200         2015-10-10 10:10:37
2      101           1750         2015-10-10 10:12:42
3      100           1100         2015-10-10 10:19:50
4      102           4100         2015-10-11 10:24:22
5      101           3000         2015-10-09 10:32:44

正如您在此处所见,player 100在此表中有两个分数。他的最终得分是1100. player 101也有两个得分,但在选定的日期他只有一个得分。 player 102在所选日期没有任何分数。

如何编写一个查询,以获取该特定日期每位玩家的最终得分记录?我想要的结果是:

player_id     score        date
------------------------------------------------------
100           1100         2015-10-10 10:19:50
101           3000         2015-10-09 10:32:44

我之前试图解决这个问题,但最终搞砸了实际的观点,它变成了一个不同的问题(我得到了一个很好的答案)。我希望有人能帮助我解决这个问题因为我真的卡在这里:(

4 个答案:

答案 0 :(得分:2)

模式

create table scores
(   id int auto_increment primary key,
    player_id int not null,
    score int not null,
    score_date datetime not null
);
insert scores(player_id,score,score_date) values
(100, 3200, '2015-10-10 10:10:37'),
(101, 1750, '2015-10-10 10:12:42'),
(100, 1100, '2015-10-10 10:19:50'),
(102, 4100, '2015-10-11 10:24:22'),
(101, 3000, '2015-10-09 10:32:44'),
(105, 6666, '2015-10-09 10:00:44');

在任何日期达到2015-10-10的最后得分

SELECT  a.player_id,a.score
FROM    scores a
JOIN
(   SELECT  player_id, MAX(score_date) as weCareAbout
    FROM    scores
    where score_date<date('2015-10-11')
    GROUP BY player_id
) b 
ON b.player_id=a.player_id and b.weCareAbout=a.score_date
order by a.player_id;
+-----------+-------+
| player_id | score |
+-----------+-------+
|       100 |  1100 |
|       101 |  1750 |
|       105 |  6666 |
+-----------+-------+

2015-10-10的最后得分,仅在该日期得分

SELECT  a.player_id,a.score
FROM    scores a
JOIN
(   SELECT  player_id, MAX(score_date) as weCareAbout
    FROM    scores
    where date(score_date)='2015-10-10'
    GROUP BY player_id
) b 
ON b.player_id=a.player_id and b.weCareAbout=a.score_date
order by a.player_id;
+-----------+-------+
| player_id | score |
+-----------+-------+
|       100 |  1100 |
|       101 |  1750 |
+-----------+-------+

请记住,我认为您的预期结果是错误的。他们的最终得分,而不是高分。

答案 1 :(得分:0)

它是一个数据透视表问题,但遗憾的是,MySQL并不具备超高效率。

子查询和ORDER BY ... LIMIT 1可以为您提供之后的结果,但效果会大幅下降。

对于效率低下的解决方案(使用子查询),例如:(无处测试,语法可能不会出现......)

SELECT player_id, score
FROM scores
INNER JOIN
  (
     SELECT
        MAX(`date`) AS `latestScoreDateTime`,
        player_id
     FROM scores
     WHERE DATE(`date`) = '2015-10-10'
     GROUP BY player_id
  ) AS sub1 ON (
     sub1.lastestScoreDateTime = scores.date AND
     sub1.player_id = scores.player_id
  )

但是在前面加EXPLAIN - 你会发现表现并不好。

就个人而言(曾经处理过一些大数据集和大数据集以及需要解决的各种问题,都要求速度和效率)我通过存储过程处理所有数据库插入(或者你自己的数据访问 - 应用程序中的图层,或[ shudder ]通过触发器。)

这个抽象层将维持一个&#34; latestForDate&#34;领域。存储过程可以以事务安全的方式执行此操作。

我没有测试区来证明这一点 - 但语法看起来大概是这样的:

DELIMTIER $$
CREATE PROCEDURE spAddPlayerScore (IN fin_playerId INT UNSIGNED, IN fin_score INT UNSIGNED)
BEGIN
   DECLARE pToday DATETIME;

   START TRANSACTION;
       SET pToday = CURDATE();

       UPDATE scores SET latest_for_date=NULL
       WHERE latest_for_date=pToday AND player_id=fin_playerId;

       INSERT INTO scores SET
          latest_for_date=pToday,
          score=fin_score,
          player_id=fin_playerId;
   COMMIT;
END$$

因此,你(交易安全地)维持一个非规范化(有效阅读!)获得最高分的方式:

SELECT * FROM scores WHERE latest_for_date='2015-10-10' GROUP BY player_id;

答案 2 :(得分:-1)

试试这个(未经测试,可能有语法错误):

CREATE TEMPORARY 
TABLE t1 (player_id int not null, score int not null, score_date datetime),UNIQUE KEY(player_id,score_date));
REPLACE INTO t1 SELECT player_id, score, score_date
FROM tbl_name
WHERE DATE(score_date) = '2015-10-01' order by player_id,score_date;
SELECT * FROM t1;

答案 3 :(得分:-1)

SELECT *
FROM (
      SELECT player_id, score, score_date
      FROM player
      ORDER BY score_date DESC
     ) temp
GROUP BY player_id, score_date