MySQL选择带有求和,限制和顺序的子查询

时间:2017-09-03 13:48:39

标签: mysql scope subquery sql-order-by limit

我需要从所有学科的每个团队中选择前3个分数的总和。更好的得分=更多积分。所以我可以显示比赛的总分。我试着跑吧......像这样:

SELECT t.name, 
  (SELECT SUM(points) FROM (SELECT points
    FROM scores
    WHERE team = t.id
    ORDER BY points DESC
    LIMIT 3) points) sum
  FROM teams t

但我得到错误:

Unknown column 't.id' in 'where clause'

这是架构和数据的链接: http://sqlfiddle.com/#!9/ecc66b/20

请帮帮我。我确信这个查询可以在MsSQL中运行,但是我被迫使用MySQL

3 个答案:

答案 0 :(得分:0)

您要做的是从外部查询中的列中访问一个值,该查询是当前查询中的外部查询。

除了问题,你不能简单地在第二个子查询中使用SUM()函数,这样就不需要第一个子查询了。

查看修改后的fiddle here

还可以找到有关该问题的更多信息here

答案 1 :(得分:0)

选择每组排名前3位(或者每组排名前N位)在MySQL中是一个非常棘手的问题,它对ROW_NUMBER,{{1}等分析函数没有任何内置支持},或RANK。正如您在SQL Server的评论中检测到的那样,在另一个支持分析函数的SQL Server中,这个问题会更容易处理。

MySQL中的一个选项是使用会话变量模拟分析函数。对于您的数据集,我们可能希望模拟密集排名。请考虑以下查询:

DENSE_RANK

<强>输出:

enter image description here

在上面的输出中仔细注意,在跑步和飞行学科之间,狗队中排名第三。你的数据包含这样的关系是好的,因为这是一个值得关注的边缘情况。事实上,这就是为什么我选择模拟密集排名,而不是行号,后者可能会随意选择两个第三位记录中的一个进行报告。

在这里演示:

Rextester

SQLFiddle

(您原来的小提琴更新)

答案 2 :(得分:0)

没有必要考虑ex aequo分数。这是完成我期望的代码。

SET @dr = 0;
SET @points = NULL;
SET @team = NULL;

SELECT
    sum(s.points) points_total,
    t.name AS team_name
FROM
(
    SELECT
        @dr:=CASE WHEN @team = team THEN @dr + 1 ELSE 1 END AS dr,
        @points:=points AS points,
        @team:=team AS team,
        discipline
    FROM scores s
    ORDER BY
        s.team,
        s.points DESC
) s
INNER JOIN teams t
    ON s.team = t.id
INNER JOIN disciplines d
    ON s.discipline = d.id
WHERE s.dr <= 3
GROUP BY 
  t.name
ORDER BY
    1 DESC;

感谢@Tim Biegeleisen展示路径。

输出:

enter image description here