【问题标题】:SQL Server 2012/2014 Calculate running countSQL Server 2012/2014 计算运行计数
【发布时间】:2015-01-29 08:12:03
【问题描述】:

我正在尝试创建一个查询,该查询将按日期返回运行计数,按模块分组。

我感兴趣的表中的字段是 DateID、Module。 Module 和 DateID 存在一行的事实表明计数为 1。一个模块可以针对单个 DateID 出现多次,并且显然每天也有多个模块。运行以下查询几乎可以返回我想要的结果:

SELECT 
    DateID,
    Module,
    ROW_NUMBER() OVER (PARTITION BY Module ORDER BY DateID) [RunningCount]
FROM dbo.vwFiles
WHERE DateID IN (5467,5468)
AND Module IN ('PC','DD','NL')
ORDER BY DateID

    DateID  Module  RunningCount
    5467    DD      1
    5467    DD      2
    5467    DD      3
    5467    NL      1
    5467    NL      2
    5467    NL      3
    5467    NL      4
    5467    PC      1
    5467    PC      2
    5467    PC      3
    5468    NL      5

但是,我不只是获得每个 DateID 的单个计数,而是获得每个 DateID 上每个模块记录的计数。

修改查询如下:

SELECT DateID, Module,MAX(RunningCount) RunningCount
FROM 
(
    SELECT DateID, Module
    , ROW_NUMBER() OVER(PARTITION BY Module ORDER BY DateID) RunningCount
    FROM vwFiles
    WHERE DateID IN (5467,5468)
    AND Module IN ('PC','DD','NL')  
) z
GROUP BY Module, DateID
ORDER BY DateID, Module

    DateID  Module  RunningCount
    5467    DD      3
    5467    NL      4
    5467    PC      3
    5468    NL      5

确实给了我想要的。但是我会认为有更简单的方法可以做到这一点?

【问题讨论】:

  • 更简单?我猜你没有计算 MS SQL 2000 中的运行总计 :)
  • 可以提供测试数据吗?
  • 据我所知,你只是在数他们

标签: sql sql-server rowcount


【解决方案1】:

您所做的根本不是“运行总数”。您只是按组计数。因此,您可以简单地执行该操作:

SELECT DateId, Module, COUNT(*) FROM vwFiles
GROUP BY DateId,Module

问题不是你面临一个复杂的问题,而是你以错误的方式面对它。

【讨论】:

  • 不太正确 JotaBe。您的解决方案不会根据需要提供“运行”计数。你的每天产生计数,这显然更容易获得。
  • 好吧,我不明白为什么问题标题说“运行总计”,然后,在问题的最后,您按日期和模块显示总计,这句压倒性的句子:“确实给我想要什么”。我错过了什么?为什么返回完全符合您期望的查询不能解决您的问题?我想你这样说肯定是有原因的,请解释一下。
  • 问题标题显示运行计数。不是“总计”。运行总计意味着一个总和,正如我所说,有很多例子和讨论。我确实接受我的第二条 SQL 语句确实给了我想要的东西,但我个人认为它有点不优雅,并且会认为会有一种本地方式来做到这一点,这就是我问的原因。
  • 好吧,我不介意它是运行总数还是运行计数。您的问题或解决方案中缺少的部分是“运行”部分。运行意味着您的查询返回一组行,其中每行的结果包括某种聚合或计数,包括直到该特定行的行。您的结果根本没有运行总计。您不必担心 SQL Server 是如何计算它的。只有得到你需要的结果才重要。强制 SQL Server 计算运行总计以仅保留总计有什么意义?那是没有意义的。我还缺少什么吗?
【解决方案2】:

运行总计是如此自然的事情,几乎令人惊讶的是没有一些本地方法可以做到这一点。这是一种不同的方法,我认为它更简单一些,但我也认为“简单”可能是一个非常主观的术语:)

declare @t table (DateId int, Module char(2))

insert @t values (5467, 'DD'),
                 (5467, 'DD'),
                 (5467, 'DD'),
                 (5467, 'NL'),
                 (5467, 'NL'),
                 (5467, 'NL'),
                 (5467, 'NL'),
                 (5467, 'PC'),
                 (5467, 'PC'),
                 (5467, 'PC'),
                 (5468, 'NL')

; with cte as (
    select
        row_number() over (order by DateId, Module) as rn,
        t.*
    from 
        @t t
)
SELECT
    t1.DateId,
    t1.Module,
    count(distinct t2.rn)
FROM
    cte AS t1
        LEFT JOIN cte AS t2 ON t2.Module = t1.Module and t2.rn <= t1.rn
GROUP BY 
    t1.DateId, 
    t1.Module
ORDER BY 
    t1.DateId,
    t1.Module

Aaron Bertrand 在 SQLPerformance.com Best approaches for running totals 上有一篇相当不错的文章 - 值得一读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多