给出以下架构:
CREATE TABLE players (
id BIGINT PRIMARY KEY,
name TEXT UNIQUE
);
CREATE TABLE trials (
timestamp TIMESTAMP PRIMARY KEY,
player BIGINT,
score NUMERIC
);
如何创建SELECT
,首先从trials
找到最佳分数,然后加入name
的{{1}}字段?在使用此查询后,我已经能够获得分数:
users
我对返回前10个分数的查询如下:
SELECT * FROM trials GROUP BY player ORDER BY score ASC LIMIT 10;
但是当我在表中搜索数千个条目时,数据库性能开始爬行。我认为子查询正在扼杀我的表现。第一个查询(仅返回最高分数)仍然可以充分执行,因此我想知道是否有办法在选择最高分后强制CREATE VIEW top10place AS
SELECT player.name AS name, trial.*
FROM trials AS trial, players AS player
WHERE trial.player = player.id
AND trial.score = (
SELECT MAX(score)
FROM trials AS tsub
WHERE tsub.player = trial.player
)
ORDER BY trial.score DESC, trial.timestamp ASC
LIMIT 10;
操作。
编辑请注意,该查询将返回排名前10位的玩家,而不仅仅是排名前10位的玩家。如果同一个玩家有很多高分,他应该只出现在前10名中。
我正在使用SQLite,因此它没有SQL Server或MySQL的某些扩展功能。
答案 0 :(得分:4)
没有运行sqlite,希望限制是正确的。
select players.name, trials.player, trials.timestamp, trials.score from
(select player, score, timestamp from
trials order by score desc, timestamp asc limit 10) trials, players
where players.id = trials.player
此致
答案 1 :(得分:1)
这是你做出比它需要更难的事情的一个例子。正确的代码是:
CREATE VIEW top10place AS
SELECT player.name AS name, trial.*
FROM trials AS trial, players AS player
WHERE trial.player = player.id
ORDER BY trial.score ASC, trial.timestamp ASC
LIMIT 10;
基本上,让LIMIT语句完成工作:)
答案 2 :(得分:1)
如果优化器为每一行运行它,那么WHERE中的子查询可能会很昂贵。
(编辑)这是编写查询的另一种方法,现在使用独占连接:它表示该用户没有排得分更高的行:
SELECT
(select name from user where id = cur.userid) as UserName
, cur.score as MaxScore
FROM trails cur
LEFT JOIN trials higher
ON higher.userid = cur.userid
AND higher.timestamp <> cur.timestamp
AND higher.score > cur.score
WHERE higher.userid is null
ORDER BY cur.score DESC
LIMIT 10
这将返回10个得分最高的用户。如果您不管用户是否想要10个最高分,请查看Silas的答案。
答案 3 :(得分:1)
正如已经提到的,由于你在玩家和试验之间的识别关键是player.id和trials.player,你应该在trial.player上有一个索引。特别是如果你把这两张桌子关联起来的话。
您也可以尝试使查询更像。
SELECT p.name as name, t.* FROM players as p
INNER JOIN (SELECT * FROM trials WHERE trials.score = (SELECT MAX(score) FROM trials as tsub WHERE tsub.player = trials.player) LIMIT 10) as t ON t.player = p.id
ORDER BY t.score DESC, t.timestamp ASC
这甚至可以进行一些优化,但如果没有一些数据可以将查询抛出,我就不擅长了。