如何从SQLITE中选择每个团队的前N名优胜者?

如何从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

我有这样一个sqlite3表:

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;