在SQL中进行查询以求出列的前n大

时间:2019-06-19 10:29:45

标签: sql sql-server group-by sum

我有两列我关心YearMonthValue

如何将Value中的第50个(第1至第50个,即第1,第2,...,第50个)最大值相加并根据条件创建新列?

我能够做SUM(CASE WHEN Value > 100 THEN Value END) AS LargeValue,但是第一个到第50个最大值每次YearMonth都会变化,所以这样做并不是完全正确。

我找不到任何解决方案,大多数答复是找到而不是总和排在第n位。

该表如下所示(简化):

====================
YearMonth Value Flow
====================
201801   500   10
201801   400   -5
 ...     ...   ...
201802   700   20
201802   100  -20 
201802   50    10

3 个答案:

答案 0 :(得分:2)

您可以使用窗口功能:

select t.*,
       sum(case when seqnum <= 50 then value end) over
           (partition by yearmonth) as top50_sum
from (select t.*,
             row_number() over (partition by yearmonth order by value desc) as seqnum
      from t
     ) t;

如果您只希望结果集中的每个yearmonth行,请使用group by

select t.yearmonth, sum(value) as top50_sum
from (select t.*,
             row_number() over (partition by yearmonth order by value desc) as seqnum
      from t
     ) t
where seqnum <= 50
group by yearmonth

答案 1 :(得分:0)

您可以使用派生表按降序对行进行排序,并将结果限制为50行。然后从中求和。

如何编写限制取决于DBMS。 LIMIT在其中许多功能中都可以使用。

SELECT sum(x.value)
       FROM (SELECT t.value
                    FROM elbat t
                    ORDER BY t.value DESC
                    LIMIT 50) x;

答案 2 :(得分:0)

SELECT t.*, 
       SUM(CASE WHEN t.r < 51 THEN t.value ELSE 0 END) OVER() runningtotal 
  FROM (
         SELECT a.yearmonth, 
                a.value, 
                RANK() OVER (ORDER BY value DESC) r 
           FROM yourtable a ) t 
 ORDER BY t.r asc

与仅针对前50个元素为排名表创建运行总计列相比,创建排名表顺序更为合适。