【问题标题】:How to select first N winners of each team from SQLITE?如何从 SQLITE 中选择每个团队的前 N ​​个获胜者?
【发布时间】:2016-07-26 09:03:07
【问题描述】:

我有一个这样的 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 查询得到这个结果?任何人都可以提供一些线索? 非常感谢。

顺便说一句,“名称”字段不是唯一的,只有(团队,名称)是唯一的,这意味着相同的名称可以出现在不同的团队中。

【问题讨论】:

  • 从分数 > 99 的分数中选择 *;和你得到的总计数然后选择 count(*) where scores > 99;

标签: sqlite limit-per-group


【解决方案1】:

你可以试试这个

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

【讨论】:

    【解决方案2】:

    根据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 分钟!此查询大约需要半小时才能完成。显然,这在实际工作中是不可能发生的。我认为必须有一些方法可以提高效率。

    【讨论】:

      【解决方案3】:

      我们可以从包含每个团队的前 N ​​个结果的表中选择结果集,而不是从 scores 表中选择每个团队的前 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文件中有一个新的表或触发器,我建议你做以下事情

      1. 创建新表leaderboarddummy_scores
      2. dummy_scores 创建触发器
      3. 使用INSERT INTO ... SELECT语句将数据从score复制到dummy_score,这也激活了触发器
      4. SELECT * FROM leaderboard获取结果
      5. 从数据库文件中删除leaderboarddummy_scores 和触发器

      现在你有了原始的 db 文件和你需要的结果。 ?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-09
        • 1970-01-01
        • 2015-03-23
        • 2018-11-05
        • 2011-03-22
        • 1970-01-01
        • 2021-03-20
        • 2023-03-17
        相关资源
        最近更新 更多