按最大总和选择,但结果中没有总和

Posted

技术标签:

【中文标题】按最大总和选择,但结果中没有总和【英文标题】:Select by greatest sum, but without the sum in the result 【发布时间】:2015-10-21 03:51:17 【问题描述】:

我需要选择玩家所有组合尝试的最高得分,并且我需要使用WITH 子句。

create table scorecard(
 id integer primary key,
 player_name varchar(20));

create table scores(
 id integer references scorecard,
 attempt integer,
 score numeric
 primary key(id, attempt));

记分卡示例数据:

id       player_name
1        Bob      
2        Steve    
3        Joe    
4        Rob    

分数的样本数据:

id    attempt    score
1        1         50
1        2         45
2        1         10
2        2         20
3        1         40
3        2         35
4        1         0
4        2         95

结果将如下所示:

player_name
Bob
Rob

但只有当 Rob 的总分低于 ​​95 时才会是 Bob。到目前为止,我已经得到了他们在两列中使用的名称和总分:

select scorecard.player_name, sum(scores.score)
from scorecard
left join scores
on scorecard.id= scores.id
group by scorecard.name
order by sum(scores.score) desc;

但是我如何才能得到最高分的名字(或者如果并列的话)。

记住,它应该使用a WITH 子句。

【问题讨论】:

创建 2 个查询:一个选择最大总分的查询。另一个计算每个球员的得分。将它们都放在WITH 中就完成了。 【参考方案1】:

曾经告诉您“使用 WITH 子句”的人错过了更有效的解决方案。只获得(可能是多个)获胜者:

SELECT c.player_name
FROM   scorecard c
JOIN  (
   SELECT id, rank() OVER (ORDER BY sum(score) DESC) AS rnk
   FROM   scores
   GROUP  BY 1
   ) s USING (id)
WHERE  s.rnk = 1;

普通子查询通常比CTE 快。如果您必须使用WITH 子句:

WITH top_score AS (
   SELECT id, rank() OVER (ORDER BY sum(score) DESC) AS rnk
   FROM   scores
   GROUP  BY 1
   )
SELECT c.player_name
FROM   scorecard c
JOIN   top_score s USING (id)
WHERE  s.rnk = 1;

SQL Fiddle.

可以添加最后一个 ORDER BY c.player_name 以获得稳定的排序顺序,但这不是要求。

查询的关键特性是您可以在聚合函数的结果上运行window function like rank()。相关:

Postgres window function and group by exception Get the distinct sum of a joined table column

【讨论】:

【参考方案2】:

可以尝试以下方法。

With (SELECT id, sum(score) as sum_scores
      FROM scores
      group by id) as sumScoresTable,

With (SELECT max(score) as max_scores
      FROM scores
      group by id) as maxScoresTable

select player_name 
FROM scorecard
WHERE scorecard.id in (SELECT sumScoresTable.id 
                       from sumScoresTable 
                       where  sumScoresTable.score = (select maxScoresTable.score from maxScoresTable)

【讨论】:

【参考方案3】:

试试这个代码:

   WITH CTE AS (
       SELECT ID, RANK() OVER(ORDER BY SumScore DESC) As R
       FROM (
          SELECT ID, SUM(score) AS SumScore
          FROM scores
          GROUP BY ID )
    )

   SELECT player_name
   FROM scorecard
   WHERE ID IN (SELECT ID FROM CTE WHERE R = 1)

【讨论】:

以上是关于按最大总和选择,但结果中没有总和的主要内容,如果未能解决你的问题,请参考以下文章

数组中的最大总和,使得可以在 5 个元素中选择最多 2 个连续的元素

mysql从表中显示数据最大值和总和

MySQL 按总和限制行数

SQL 合并总和选择一个结果

SQL选择列的总和最大的行(在GROUP BY中有两个字段)

分组总和的平均值