累积总和的 SQL 查询

Rol*_*and 5 sql-server sql-server-2012 sum running-totals

我在制定(相对)简单的 SQL 查询(使用 SQL Server 2012)时遇到问题。我们有一个数据库,可以为某些用户计算一些东西。因此,我们有一个非常简单的数据库结构,由两个表组成。

users

PK_User, uniqueidentifier
ID, bigint
Username, nvarchar(128)
CreationTimestamp, datetime
Run Code Online (Sandbox Code Playgroud)

data

PK_Data, uniqueidentifier
FK_User, uniqueidentifier
FK_Reporter, uniqueidentifier
CreationTimestamp, datetime
Run Code Online (Sandbox Code Playgroud)

我目前正在使用以下 SQL 语句:

SELECT u.Username, COUNT(d.FK_User) AS 'Count', CAST(FLOOR(CAST(d.CreationTimestamp AS float)) AS datetime) AS 'Date'
FROM data d INNER JOIN users u ON u.PK_User = d.FK_User
GROUP BY CAST(FLOOR(CAST(d.CreationTimestamp AS float)) AS datetime), u.Username
ORDER BY CAST(FLOOR(CAST(d.CreationTimestamp AS float)) AS datetime)
Run Code Online (Sandbox Code Playgroud)

它提供了这样的东西:

User1   5   %Date1%
User2   3   %Date1%
User1   7   %Date2%
User2   1   %Date2%
Run Code Online (Sandbox Code Playgroud)

所以我能够获得每个特定日期每个用户的总和。我想总结一下这个总和,以便用户1获得第二天5+7=12和用户2 3+1=4。

我怎样才能做到这一点?

ype*_*eᵀᴹ 9

您需要一个“窗口”聚合,即聚合中的一个OVER子句。而且由于查询已经有一个GROUP BY,需要的骨料是SUM()COUNT(d.FK_User)你已经有:

SELECT 
    u.Username, 
    -- COUNT(d.FK_User) AS UserCount,     -- if you need both counts
    SUM(COUNT(d.FK_User)) OVER (PARTITION BY u.Username
                                ORDER BY CAST(d.CreationTimestamp AS DATE)
                                ROWS BETWEEN UNBOUNDED PRECEDING
                                         AND CURRENT ROW) 
        AS CumulativeUserCount, 
    CAST(d.CreationTimestamp AS DATE) AS CreationDate
FROM data d 
    INNER JOIN users u 
    ON u.PK_User = d.FK_User
GROUP BY 
    CAST(d.CreationTimestamp AS DATE), u.Username
ORDER BY
    CreationDate ;
Run Code Online (Sandbox Code Playgroud)
  • ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW并不是必需的。当有一个ORDER BYinside时,窗口聚合的默认框架OVER ()RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,这将产生相同的结果,ROWS但可能会生成一个次优的执行计划。有关详细信息,请参阅Aaron Bertrand的博客文章运行总计的最佳方法 – 针对 SQL Server 2012 更新
  • 我已经简化了似乎只是从日期时间列中去除时间部分的复杂表达式。
  • 删除了别名周围的单引号。别名和标识符最好不要是保留关键字,也不要有特殊字符或空格。如果您确实需要其中任何一个,那么最好用双引号"Count"或方括号引用它们[Count]