【问题标题】:T-SQL using SUM for a running totalT-SQL 使用 SUM 计算运行总计
【发布时间】:2012-08-16 06:45:19
【问题描述】:

我有一个简单的表,其中包含一些虚拟数据设置,例如:

|id|user|value|
---------------
 1  John   2
 2  Ted    1
 3  John   4
 4  Ted    2

我可以通过执行以下 sql(MSSQL 2008) 语句来选择运行总计:

SELECT a.id, a.user, a.value, SUM(b.value) AS total
FROM table a INNER JOIN table b
ON a.id >= b.id
AND a.user = b.user
GROUP BY a.id, a.user, a.value
ORDER BY a.id

这会给我这样的结果:

|id|user|value|total|
---------------------
 1  John   2     2
 3  John   4     6
 2  Ted    1     1
 4  Ted    2     3

现在是否可以只检索每个用户的最新行?所以结果是:

|id|user|value|total|
---------------------
 3  John   4     6
 4  Ted    2     3

我这样做的方式是否正确?任何建议或遵循的新路径都会很棒!

【问题讨论】:

  • 您是只对最终结果感兴趣,还是还需要运行总数?您是否已经将运行总数存储在某个地方,还是仅使用它来生成最终结果? [您的最终结果可以更有效地创建,而无需使用运行总计。但是,如果您已经将运行总数存储在某个地方,出于其他原因,它当然可以使用。]
  • 您更改了您接受的答案以提高性能,但您没有回复我上面的查询。请注意,您可以通过使用运行总计方法来提高性能。您是否会对此感兴趣,或者您是否需要以及中的所有结果?
  • 嗨,Dems,我忙于工作,错过了您的评论。我只关注总用户和相关用户,所以是的,我对提高性能感兴趣。

标签: sql sql-server-2008 tsql


【解决方案1】:

不需要join,这样可以加快查询速度:

select id, [user], value, total
from
(
  select id, [user], value, 
  row_number() over (partition by [user] order by id desc) rn, 
  sum(value) over (partition by [user]) total
from users
) a
where rn = 1

【讨论】:

  • 这可以通过显式声明SUM OVER的over子句的附加参数来进一步加快速度
【解决方案2】:

试试这个:

;with cte as 
     (SELECT a.id, a.[user], a.value, SUM(b.value) AS total
    FROM users a INNER JOIN users b
    ON a.id >= b.id
    AND a.[user] = b.[user]
    GROUP BY a.id, a.[user], a.value
     ),
cte1 as (select *,ROW_NUMBER() over (partition by [user] 
                         order by total desc) as row_num
         from cte)
select  id,[user],value,total from cte1 where row_num=1

SQL Fiddle Demo

【讨论】:

  • @Joe G Joseph,看起来指向 SQL Fiddle 的链接已损坏。
【解决方案3】:

添加where语句:

select * from
(
your select statement
) t

where t.id in (select max(id) from table group by user)

你也可以使用这个查询:

SELECT a.id, a.user, a.value, 

(select max(b.value) from table b where b.user=a.user) AS total

FROM table a 

where a.id in (select max(id) from table group by user)

ORDER BY a.id

【讨论】:

    【解决方案4】:

    添加右连接会比嵌套选择执行得更好。

    甚至更简单:

    SELECT MAX(id), [user], MAX(value), SUM(value)
    FROM table
    GROUP BY [user]
    

    【讨论】:

    • 但是 max(id) 和 max(value) 可以来自不同的原始表行。
    • -1 :这是一种过于简单的方法,根本无法正常工作。您不能假设 MAX(id) 和 MAX(value) 从同一输入行给出结果。
    • 你是对的,我发帖后才意识到。但是,智能右连接仍然比嵌套选择执行得更好。
    【解决方案5】:

    与 SQL Server 2008 或更高版本兼容

    DECLARE @AnotherTbl TABLE
        (
            id           INT
          , somedate     DATE
          , somevalue    DECIMAL(18, 4)
          , runningtotal DECIMAL(18, 4)
        )
    
    INSERT INTO @AnotherTbl
        (
            id
          , somedate
          , somevalue
          , runningtotal
        )
    SELECT  LEDGER_ID
          , LL.LEDGER_DocDate
          , LL.LEDGER_Amount
          , NULL
    FROM    ACC_Ledger LL
    ORDER BY LL.LEDGER_DocDate
    
    DECLARE @RunningTotal DECIMAL(18, 4)
    SET @RunningTotal = 0
    
    UPDATE  @AnotherTbl
    SET @RunningTotal=runningtotal = @RunningTotal + somevalue
    FROM    @AnotherTbl
    
    SELECT  *
    FROM    @AnotherTbl
    

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 2018-10-10
      • 2010-10-26
      • 1970-01-01
      • 2019-03-19
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多