【问题标题】:Cumulative sum of a column一列的累计和
【发布时间】:2021-05-21 22:15:16
【问题描述】:

我有一个包含以下数据的表格。

COUNTRY LEVEL   NUM_OF_DUPLICATES
  US    9           6
  US    8           24
  US    7           12
  US    6           20
  US    5           39
  US    4           81
  US    3           80
  US    2           430
  US    1           178
  US    0           430

我写了一个查询来计算累积行的总和并得到以下输出。

COUNTRY LEVEL   NUM_OF_DUPLICATES      POOL
  US    9           6                   6
  US    8           24                  30
  US    7           12                  42
  US    6           20                  62
  US    5           39                  101
  US    4           81                  182
  US    3           80                  262
  US    2           130                 392
  US    1           178                 570
  US    0           254                 824

现在我想过滤数据,只取 POOL

COUNTRY LEVEL   NUM_OF_DUPLICATES      POOL
  US    9           6                   6
  US    8           24                  30
  US    7           12                  42
  US    6           20                  62
  US    5           39                  101
  US    4           81                  182
  US    3           80                  262
  US    2           130                 392

请告诉我你的想法。提前致谢。

【问题讨论】:

  • 根据问题指南,请展示您尝试过的内容并告诉我们您发现了什么(在本网站或其他地方)以及为什么它不能满足您的需求。如果您将示例数据以 DDL+DML 的形式发布,那么人们可以更轻松地提供帮助。
  • 我们如何对行进行排序(记住表没有内在的排序)?您想以越来越多的NUM_OF_DUPLICATES 订购它们吗?还有什么?

标签: sql sql-server tsql cumulative-sum


【解决方案1】:
declare @t table(Country varchar(5), Level int, Num_of_Duplicates int)
insert into @t(Country, Level, Num_of_Duplicates)
values
('US', 9, 6),
('US', 8, 24),
('US', 7, 12),
('US', 6, 20),
('US', 5, 39),
('US', 4, 81),
('US', 3, 80),
('US', 2, 130/*-92*/),
('US', 1, 178),
('US', 0, 430);


select *, sum(Num_of_Duplicates) over(partition by country order by Level desc),
(sum(Num_of_Duplicates) over(partition by country order by Level desc)-Num_of_Duplicates) / 300 as flag,--any row which starts before 300 will have flag=0
--or
case when sum(Num_of_Duplicates) over(partition by country order by Level desc)-Num_of_Duplicates < 300 then 1 else 0 end as startsbefore300
from @t;

select *
from
   (
    select *, sum(Num_of_Duplicates) over(partition by country order by Level desc) as Pool
    from @t
) as t
where Pool - Num_of_Duplicates < 300 ;

【讨论】:

  • 我已经试过了,但是如果有新记录怎么办
  • ..@Vinay .. 我猜你已经尝试过新的&任意数量的行......
【解决方案2】:

这里的逻辑很简单:

  • 计算直到当前行的运行总和POOL
  • 过滤行,使前一行的总数
  • 如果到当前行的总数正好是 300,则上一行会少,所以会包括这一行
  • 如果当前行的总数超过300,而上一行小于那么也会被包含进来
  • 排除所有较高的行

不清楚您想要什么顺序。我使用了NUM_OF_DUPLICATES 列升序,但您可能想要别的东西

SELECT
    COUNTRY,
    LEVEL,
    NUM_OF_DUPLICATES,
    POOL
FROM (
    SELECT *,
        POOL = SUM(NUM_OF_DUPLICATES) OVER (ORDER BY NUM_OF_DUPLICATES ROWS UNBOUNDED PRECEDING)
        -- alternative calculation
        -- ,POOLPrev = SUM(NUM_OF_DUPLICATES) OVER (ORDER BY NUM_OF_DUPLICATES ROWS UNBOUNDED PRECEDING AND 1 PRECEDING)
    FROM YourTable
) t
WHERE POOL - NUM_OF_DUPLICATES < 300;
-- you could also use POOLPrev above

【讨论】:

    【解决方案3】:

    我使用了两个临时表来得到答案。

     DECLARE @t TABLE(Country VARCHAR(5), [Level] INT, Num_of_Duplicates INT)
     INSERT INTO @t(Country, Level, Num_of_Duplicates)
      VALUES ('US', 9, 6),
          ('US', 8, 24),
          ('US', 7, 12),
          ('US', 6, 20),
          ('US', 5, 39),
          ('US', 4, 81),
          ('US', 3, 80),
          ('US', 2, 130),
          ('US', 1, 178),
          ('US', 0, 254);
    
    
    SELECT 
        Country
        ,Level
        , Num_of_Duplicates
        , SUM (Num_of_Duplicates) OVER (ORDER BY id) AS [POOL]
     INTO #temp_table
    FROM
       (
        SELECT
            Country,
            level,
            Num_of_Duplicates,
            ROW_NUMBER() OVER (ORDER BY country) AS id
        FROM    @t
     ) AS A 
    
    
    SELECT  
        [POOL],
        ROW_NUMBER() OVER (ORDER BY [POOL] )   AS [rank]
    INTO #Temp_2
    FROM  #temp_table 
    WHERE [POOL] >= 300
    
    
    SELECT * 
    
    FROM #temp_table WHERE 
    [POOL]   <= (SELECT [POOL] FROM #Temp_2 WHERE [rank] = 1 ) 
    
        
    DROP TABLE #temp_table
    DROP TABLE #Temp_2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 2020-01-02
      • 2014-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多