我有一个像这样的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个团队),每个团队都有很多成员(实际记录超过10,000个)。我只想得到每个团队的前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查询获得此结果?谁能提供一些线索? 非常感谢。
顺便说一下,'姓名'字段非唯一,只有(团队,名称)是UNIQUE,这意味着同一名称可以出现在不同的团队中。答案 0 :(得分:0)
你可以试试这个
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
答案 1 :(得分:0)
根据Question: how to select first N row of each group?,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分钟!此查询大约需要半小时才能完成。显然,这不可能在实际工作中发生。我认为必须有一些方法来提高效率。
答案 2 :(得分:0)
我们可以从表中选择结果集,而不是从scores
表中选择每个团队的前N个结果,其中包含每个团队的前N个结果。
让我们将所需数据称为leaderboard
,其结构等于scores
。
我们将插入score
的数据复制到leaderboard
。然后我们只保留leaderboard
中每个团队的最佳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文件中有新表或触发器,我建议您执行以下操作
leaderboard
和dummy_scores
dummy_scores
INSERT INTO ... SELECT
语句将数据从score
复制到dummy_score
,这也会激活触发器SELECT * FROM leaderboard
leaderboard
,dummy_scores
和db file 现在您拥有原始数据库文件以及所需的结果。