SQL-每行的前N个值之和

时间:2018-10-28 23:19:24

标签: mysql sql sum top-n

这是我的SQL表。

+-------+------+------+------+------+
| name  | q1   | q2   | q3   | q4   |
+-------+------+------+------+------+
| Alex  |    5 |    4 |   10 |    7 |
| Brown |    7 |    6 |    4 |    1 |
| Chris |   10 |   10 |    9 |   10 |
| Dave  |    8 |    4 |    6 |    0 |
+-------+------+------+------+------+

我想在上面的SQL查询中汇总每个用户的前2个得分。

例如,Alex的前2个得分分别为107,因此总和为10 + 7 = 17

我尝试了以下查询:

SELECT NewStudents.name, SUM(q1+q2+q3+q4) FROM NewStudents 
GROUP BY NewStudents.name;

要对所有q1, q2, q3, q4求和,但此查询会将所有q1q4求和,而不是q1q4中的前2个得分。

如何在mySQL中构造要执行的语句?

3 个答案:

答案 0 :(得分:2)

如@Shadow注释中所述。.您的数据库需要再次重构..因为这不是数据库的工作..您可以重构并进行这样的设计。.

+-------+----+--------+
| name  |  q | point  |
+-------+----+--------+
| Alex  |  1 |      5 |
| Alex  |  2 |      4 |
| Alex  |  3 |     10 |
| Alex  |  4 |      7 |
| Brown |  1 |      7 |
| Brown |  2 |      6 |
| Brown |  3 |      4 |
| Brown |  4 |      1 |
| Chris |  1 |     10 |
| Chris |  2 |     10 |
| Chris |  3 |      9 |
| Chris |  4 |     10 |
| Dave  |  1 |      8 |
| Dave  |  2 |      4 |
| Dave  |  3 |      6 |
| Dave  |  4 |      0 |
+-------+----+--------+

对于查询,您可以这样做:

select
     name, sum(point)
from(
     select 
          name, q, point,
          ROW_NUMBER() OVER (PARTITION BY name ORDER BY point DESC) as ranked
     from newstudents) rankedSD
where
     ranked in (1,2)
group by 
     name

您可以在此处查看演示:

Demo<>Fiddle

编辑:您可以使用Window Function。您可以阅读Row_Number() Function

答案 1 :(得分:1)

归一化的设计可能看起来像这样:

name q score
Alex  1  5
Alex 2  4
Alex 3 10
Alex 4  7

答案 2 :(得分:-1)

在旧版本的MySQL中,您可以为此使用变量:

select name, sum(q)
from (select nq.*,
             (@rn := if(@n = name, @rn + 1,
                        if(@n := name, 1, 1)
                       )
             ) as rn
      from (select nq.*
            from ((select name, q1 as q from t
                  ) union all
                  (select name, q2 as q from t
                  ) union all
                  (select name, q3 as q from t
                  ) union all
                  (select name, q4 as q from t
                  )
                 ) nq
            order by name, q desc
           ) nq cross join
           (select @n := '', @rn := 0) params
      ) nq
where rn <= 2;