我有一张桌子,根据日期存储每位玩家的得分。玩家可以在完成游戏的同一天保存多个分数。日期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
我之前试图解决这个问题,但最终搞砸了实际的观点,它变成了一个不同的问题(我得到了一个很好的答案)。我希望有人能帮助我解决这个问题因为我真的卡在这里:(
答案 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');
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 |
+-----------+-------+
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