【问题标题】:Finding group maxes in SQL join result [duplicate]在 SQL 连接结果中查找组最大值 [重复]
【发布时间】:2012-11-20 08:32:45
【问题描述】:

可能重复:
SQL: Select first row in each GROUP BY group?

两个 SQL 表。一位参赛者有很多参赛作品:

Contestants     Entries
Id   Name       Id  Contestant_Id  Score
--   ----       --  -------------  -----
1    Fred       1   3              100
2    Mary       2   3              22
3    Irving     3   1              888
4    Grizelda   4   4              123
                5   1              19
                6   3              50

低分获胜。需要按分数排序检索所有参赛者的当前最佳分数:

Best Entries Report
Name     Entry_Id  Score
----     --------  -----
Fred     5         19
Irving   2         22
Grizelda 4         123

我当然可以通过许多查询来完成这项工作。我的问题是是否有办法通过一个高效的 SQL 查询来获得结果。我几乎可以看到如何使用GROUP BY,但不完全是。

如果相关,环境是 Rails ActiveRecord 和 PostgreSQL。

【问题讨论】:

    标签: sql postgresql activerecord join


    【解决方案1】:

    这是执行此操作的特定 postgresql 方式:

    SELECT DISTINCT ON (c.id) c.name, e.id, e.score
    FROM Contestants c
    JOIN Entries e ON c.id = e.Contestant_id
    ORDER BY c.id, e.score
    

    关于DISTINCT ON的详细信息是here

    我的SQLFiddle 示例。

    UPD 按分数排序结果:

    SELECT *
    FROM (SELECT DISTINCT ON (c.id) c.name, e.id, e.score
          FROM Contestants c
          JOIN Entries e ON c.id = e.Contestant_id
          ORDER BY c.id, e.score) t
    ORDER BY score
    

    【讨论】:

      【解决方案2】:

      最简单的方法是使用排名函数:

      select name, Entry_id, score
      from (select e.*, c.name,
                   row_number() over (partition by e.contestant_id order by score) as seqnum
            from entries e join
                 contestants c
                 on c.Contestant_id = c.id
           ) ec
      where seqnum = 1
      

      【讨论】:

      • 不是最简单的方法。对于这个特定的任务(为每个不同的值选择一个记录)postgresql 有特殊的子句 - DISTINCT ON ()。详情见我的回答。
      【解决方案3】:

      我对 PostgreSQL 不熟悉,但这些方面的东西应该可以工作:

      SELECT c.*, s.Score
      FROM Contestants c
      JOIN (SELECT MIN(Score) Score, Contestant_Id FROM Entries GROUP BY Contestant_Id) s
      ON c.Id=s.Contestant_Id
      

      【讨论】:

        【解决方案4】:

        解决方案之一是

        select min(e.score),c.name,c.id from entries e
        inner join contestants c on e.contestant_id = c.id
        group by e.contestant_id,c.name,c.id
        

        这里是例子 http://sqlfiddle.com/#!3/9e307/27

        【讨论】:

          【解决方案5】:

          这个简单的查询应该可以解决问题..

          Select contestants.name as name, entries.id as entry_id,  MIN(entries.score) as score
          FROM entries
          JOIN contestants ON contestants.id = entries.contestant_id
          GROUP BY name
          ORDER BY score
          

          这会获取每个参赛者的最低分数并将他们排序为 ASC

          【讨论】:

          • 这很干净,但不幸的是 PosgreSQL 要求 GROUP BY 包含 entry_id 字段,这使得分组无用。
          猜你喜欢
          • 1970-01-01
          • 2015-05-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-22
          • 1970-01-01
          • 2017-07-03
          • 1970-01-01
          • 2013-06-24
          相关资源
          最近更新 更多