SQL 服务器 2012/2014 计算 运行 计数
SQL Server 2012/2014 Calculate running count
我正在尝试创建一个查询,它将 return 运行 按日期计数,按模块分组。
我感兴趣的 table 字段是 DateID、模块。 Module 和 DateID 存在一行这一事实表明计数为 1。一个模块可以针对单个 DateID 出现多次,显然每天也有多个模块。 运行 以下查询几乎 return 是我想要的:
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
确实给了我想要的。不过我还以为有更简单的方法呢?
运行 总计是如此自然的事情,几乎令人惊讶的是没有一些本地方法来做到这一点。这是一种不同的方法,我认为它更简单一些,但我也认为 'simple' 可能是一个非常主观的术语 :)
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 上发表了一篇相当不错的文章 - 值得一读。
你所做的根本不是 "running total"。您只是按组计数。所以,你可以简单地做那个操作:
SELECT DateId, Module, COUNT(*) FROM vwFiles
GROUP BY DateId,Module
问题不在于你面对的是一个复杂的问题,而是你面对它的方式不对。
我正在尝试创建一个查询,它将 return 运行 按日期计数,按模块分组。
我感兴趣的 table 字段是 DateID、模块。 Module 和 DateID 存在一行这一事实表明计数为 1。一个模块可以针对单个 DateID 出现多次,显然每天也有多个模块。 运行 以下查询几乎 return 是我想要的:
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
确实给了我想要的。不过我还以为有更简单的方法呢?
运行 总计是如此自然的事情,几乎令人惊讶的是没有一些本地方法来做到这一点。这是一种不同的方法,我认为它更简单一些,但我也认为 'simple' 可能是一个非常主观的术语 :)
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 上发表了一篇相当不错的文章 - 值得一读。
你所做的根本不是 "running total"。您只是按组计数。所以,你可以简单地做那个操作:
SELECT DateId, Module, COUNT(*) FROM vwFiles
GROUP BY DateId,Module
问题不在于你面对的是一个复杂的问题,而是你面对它的方式不对。