如何从SQLITE中选择每个团队的前N名优胜者?
我有这样一个sqlite3表:如何从SQLITE中选择每个团队的前N名优胜者?,sqlite,limit-per-group,Sqlite,Limit Per Group,我有这样一个sqlite3表: sqlite> select * from scores; team Name score ---------- --------- ---------- A Name1 93 A Name2 96 A Name3 78 A Name4 82 B Name5 83 B
sqlite> select * from scores;
team Name score
---------- --------- ----------
A Name1 93
A Name2 96
A Name3 78
A Name4 82
B Name5 83
B Name6 30
B Name7 99
B Name8 71
B Name8A 45
B Name8C 70
c Name9 87
c Name10 87
c Name11 81
c Name12 71
c Name13 91
有很多队,大约30个队,每个队都有很多队员,有10000多条记录。为了简化起见,我只想得到每个团队的前N名获奖者,在本例中,N=3:
A Name2 96
A Name1 93
A Name4 82
B Name7 99
B Name5 83
B Name8 71
C Name13 91
C Name9 87
C Name10 87
他们在同一队中的得分排名
如何使用sqlite3查询获得此结果?有人能提供一些线索吗?
非常感谢
顺便说一句,“Name”字段不是唯一的,只有team,Name是唯一的,这意味着相同的名称可以出现在不同的team中。您可以试试这个
set @currcount=0,@currvalue='', @N=4;
SELECT team, Name, score FROM ( SELECT team, Name, score, @currcount :=
IF(@currvalue = team, @currcount + 1, 1) as rank, @currvalue := team FROM
scores ORDER BY team DESC) as what WHERE rank<@N order by team asc, score desc
你可以试试这个
set @currcount=0,@currvalue='', @N=4;
SELECT team, Name, score FROM ( SELECT team, Name, score, @currcount :=
IF(@currvalue = team, @currcount + 1, 1) as rank, @currvalue := team FROM
scores ORDER BY team DESC) as what WHERE rank<@N order by team asc, score desc
根据Gordon Linoff的方法,我算出了以下代码:
select * from dayobs a
where a.rowid in
(select b.rowid from dayobs b where b.station==a.station order by b.rain desc limit 5);
它可以工作,但速度非常慢,sqlite提供的每个记录都超过1分钟!完成此查询大约需要半小时。显然,这在实际工作中是不可能发生的。我想一定有办法提高效率。根据Gordon Linoff的方法,我算出了以下代码:
select * from dayobs a
where a.rowid in
(select b.rowid from dayobs b where b.station==a.station order by b.rain desc limit 5);
它可以工作,但速度非常慢,sqlite提供的每个记录都超过1分钟!完成此查询大约需要半小时。显然,这在实际工作中是不可能发生的。我认为一定有更有效的方法。我们可以从包含每个团队前N名结果的表格中选择结果集,而不是从分数表中选择每个团队前N名的结果 让我们将包含我们所需数据的表格称为排行榜,其结构等于分数 我们将插入评分的数据复制到排行榜。然后我们只保留每个团队在排行榜中的最佳N分,并从中删除任何不够高的分数。为此,我们需要一个触发器,如下所示:
CREATE TRIGGER "update_top_scores"
AFTER INSERT ON scores
BEGIN
-- Add the record to leaderboard
INSERT INTO leaderboard (team, name, score) VALUES (NEW.team, NEW.name, NEW.score);
-- only keep the top 30 records of each teams
DELETE FROM leaderboard WHERE team = NEW.team AND name NOT IN (SELECT name FROM leaderboard WHERE team = NEW.team ORDER BY score DESC LIMIT 30);
END
因此,现在我们可以使用一个简单的查询从每个团队获得前N个分数
SELECT * FROM leaderboard;
假设您不想在db文件中有一个新表或触发器,我建议您执行以下操作
创建新的表格排行榜和虚拟分数
为虚拟分数创建触发器
使用插入到。。。SELECT语句将数据从分数复制到伪分数,这也会激活触发器
从排行榜中选择*获取结果
从db文件中删除排行榜、虚拟_分数和触发器
现在您有了原始的db文件和所需的结果 我们可以从包含每个团队前N名结果的表中选择结果集,而不是从分数表中选择每个团队前N名的结果 让我们将包含我们所需数据的表格称为排行榜,其结构等于分数 我们将插入评分的数据复制到排行榜。然后我们只保留每个团队在排行榜中的最佳N分,并从中删除任何不够高的分数。为此,我们需要一个触发器,如下所示:
CREATE TRIGGER "update_top_scores"
AFTER INSERT ON scores
BEGIN
-- Add the record to leaderboard
INSERT INTO leaderboard (team, name, score) VALUES (NEW.team, NEW.name, NEW.score);
-- only keep the top 30 records of each teams
DELETE FROM leaderboard WHERE team = NEW.team AND name NOT IN (SELECT name FROM leaderboard WHERE team = NEW.team ORDER BY score DESC LIMIT 30);
END
因此,现在我们可以使用一个简单的查询从每个团队获得前N个分数
SELECT * FROM leaderboard;
假设您不想在db文件中有一个新表或触发器,我建议您执行以下操作
创建新的表格排行榜和虚拟分数
为虚拟分数创建触发器
使用插入到。。。SELECT语句将数据从分数复制到伪分数,这也会激活触发器
从排行榜中选择*获取结果
从db文件中删除排行榜、虚拟_分数和触发器
现在您有了原始的db文件和所需的结果。从分数>99的分数中选择*;然后选择count*where scores>99;从分数>99的分数中选择*;然后选择count*where scores>99;