Sql 处理后加入选择
给定以下模式:Sql 处理后加入选择,sql,optimization,sqlite,join,Sql,Optimization,Sqlite,Join,给定以下模式: CREATE TABLE players ( id BIGINT PRIMARY KEY, name TEXT UNIQUE ); CREATE TABLE trials ( timestamp TIMESTAMP PRIMARY KEY, player BIGINT, score NUMERIC ); 我如何创建一个SELECT,首先从试用中找到最好的分数,然后从用户那里加入name字段?使用此查询后,我已能够获得我的分数: SELECT * FROM
CREATE TABLE players (
id BIGINT PRIMARY KEY,
name TEXT UNIQUE
);
CREATE TABLE trials (
timestamp TIMESTAMP PRIMARY KEY,
player BIGINT,
score NUMERIC
);
我如何创建一个SELECT,首先从试用中找到最好的分数,然后从用户那里加入name字段?使用此查询后,我已能够获得我的分数:
SELECT * FROM trials GROUP BY player ORDER BY score ASC LIMIT 10;
我返回前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;
但是,当我在表中点击数千个条目时,DB性能开始爬升。我认为子查询正在扼杀我的性能。第一个只返回最高分的查询仍能充分执行,因此我想知道是否有办法在选择最高分后强制执行联接操作
请注意,查询将返回排名前10名的玩家,而不仅仅是前10名的分数。如果同一名球员有很多高分,他应该在前十名中只出现一次
我使用的是SQLite,因此它没有SQL Server或MySQL的一些扩展功能。这是一个使事情变得比需要的更困难的例子。正确的代码是:
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语句来完成这项工作:如果优化器为每一行运行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的答案。正如前面提到的,因为您在玩家和试用之间的识别键是player.id和trials.player,因此您应该在trials.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
这甚至可以再优化一点,但如果没有一些数据来抛出查询,我就不擅长这样做。没有运行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
关于是否应该按试用顺序排列。分数描述?这种方法的问题是,如果同一名球员必须获得前10名的分数,他们都会出现。我在寻找排名靠前的球员,所以这个列表中只有唯一的球员。@Andomar是的,那是我的错。。。我最初的问题有一个拼写错误。这种方法在我的数据库上也非常慢,有10000名玩家和100000次试用。它需要几分钟才能完成。你能提供另一种可能性吗?@jheddings:编辑后可以用另一种方式来写这个问题。。。使用这种方法在<2秒内执行的查询,如果使用索引,则执行时间<500毫秒。谢谢