Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 检索每个名称前n-4个点的总和_Mysql_Sql_Database - Fatal编程技术网

Mysql 检索每个名称前n-4个点的总和

Mysql 检索每个名称前n-4个点的总和,mysql,sql,database,Mysql,Sql,Database,如何检索每个名称前n-4个点的总和。我们可以在一个SQL语句中完成这项工作,而不使用用户定义的会话变量吗 输入: 看看下面或下面 输出: 看看下面或下面 总结: 杰夫=7+5+4+4=20 Kat=8+5+5+4=22 尼尔=10+7+5+0=22 里克=9+8+3+2=22 输入数据库: ±±±±+ |姓名|作业|分数| ±±±±+ |杰夫| 1 | 7 | |杰夫| 2 | 5 | |杰夫| 3 | 3 | |杰夫| 4 | 4 | |杰夫| 5 | 4 | |凯特| 1 | 4 | |凯特

如何检索每个名称前n-4个点的总和。我们可以在一个SQL语句中完成这项工作,而不使用用户定义的会话变量吗

输入: 看看下面或下面

输出: 看看下面或下面

总结:
杰夫=7+5+4+4=20
Kat=8+5+5+4=22
尼尔=10+7+5+0=22
里克=9+8+3+2=22

输入数据库:
±±±±+
|姓名|作业|分数|
±±±±+
|杰夫| 1 | 7 |
|杰夫| 2 | 5 |
|杰夫| 3 | 3 |
|杰夫| 4 | 4 |
|杰夫| 5 | 4 |
|凯特| 1 | 4 |
|凯特| 2 | 8 |
|凯特| 3 | 5 |
|凯特| 4 | 3 |
|凯特| 5 | 5 |
|尼尔| 1 | 5 |
|尼尔| 2 | 7 |
|尼尔| 3 | 10 |
|尼尔| 4 | 0 |
|尼尔| 5 | 0 |
|瑞克| 1 | 2 |
|瑞克| 2 | 1 |
|瑞克| 3 | 8 |
|里克| 4 | 3 |
|里克| 5 | 9 |
±±±±+

输出: ±±±±+
|姓名|作业|分数|
±±±±+
|杰夫| 20 |
|凯特| 22 |
|尼尔| 22 |
|里克| 22 |
±±±±+


谢谢

MySQL 8+中最简单的解决方案是:

select name, sum(points)
from (select t.*, row_number() over (partition by name order by points desc) as seqnum
      from t
     ) t
where seqnum <= 4
group by name;
但是MySQL不允许这种语法。如果点没有重复项,则这将起作用:

select t.name, sum(t.points)
from t
where t.points >= coalesce( (select t2.points
                             from t t2
                             where t2.name = t.name
                             order by t2.points desc
                             limit 1 offset 3
                            ), 0)
group by t.name;
但是如果第4行和第5行的点数相同,那么总和中的行数将超过4行

现在,你可以用变量来解决这个问题。但是,我们可以采用最后一种解决方案:

select t.name,
       (case when count(*) = 4 then sum(t.points)
             else sum(t.points) - (count(*) - 4) * min(t.points)
        end)
from t
where t.points >= coalesce( (select t2.points
                             from t t2
                             where t2.name = t.name
                             order by t2.points desc
                             limit 1 offset 3
                            ), 0)
group by t.name;
这考虑到了任何联系。严格地说,
案例
是不必要的,但我认为它使逻辑更加明确

编辑:

如果你只想要倒数第四名(你的问题不清楚),同样的方法也适用:

select t.name,
       (case when count(*) = 4 then sum(t.points)
             else sum(t.points) - (count(*) - 4) * min(t.points)
        end)
from t
where t.points >= coalesce( (select t2.points
                             from t t2
                             where t2.name = t.name
                             order by t2.points asc
                             limit 1 offset 3
                            ), 0)
group by t.name;

唯一的区别是颠倒顺序。

看看MySQL是否在子查询中不允许
LIMIT
;为什么它允许内部
合并()
+1嗨,谢谢,我很确定这会返回前4个元素,而不是n-4(n是作业的数量)
select t.name,
       (case when count(*) = 4 then sum(t.points)
             else sum(t.points) - (count(*) - 4) * min(t.points)
        end)
from t
where t.points >= coalesce( (select t2.points
                             from t t2
                             where t2.name = t.name
                             order by t2.points asc
                             limit 1 offset 3
                            ), 0)
group by t.name;