对于 SQL 服务器中所选列没有值的日期,显示日期 + 小时计数为 0

Show Date + Hour 0 count for dates that have no values for selected column in SQL Server

我的最终目标是获取每周、每个类别、每周的记录出现次数的最小值、最大值、平均值和 StDEV。我无法找到一种构建 CTE 或 Temp table 的好方法,该 CTE 或 Temp table 具有记录计数,包括每天每个类别每小时 0 计数。我的报告 table 有每天的记录,但不是每天的每个小时。我尝试做一个递归 CTE,并且 运行 进入 100 个最大递归。我是 运行 SQL 2012。用我所拥有的,我可以获得准确的最大值和平均值,但不是 STDEV 或 MIN。

Declare @StartDate as DateTime
Set @StartDate = '20160101 00:00:00'
;
With Data as
(   
    Select 
        CAST(r.MyTimeStamp as Date) 'Record Date',
        DATENAME(WEEKDAY,r.MyTimeStamp) 'Day of Week',
        DATEPART(DW,r.MyTimeStamp) 'DayWeekNum',
        o.Category, 
        DATEPART(Hour,r.MyTimeStamp)'HourofDay'

    From Report r
    join [Order] o on r.ReportID = o.ReportID
    Where r.MyTimeStamp > @StartDate
),
DayCount1 as 
(   Select Distinct CAST(r.MyTimeStamp as date) 'The Date'
    , DATENAME(weekday,r.MyTimeStamp) 'Day of Week'
    From Report r
    Where r.MyTimeStamp > @StartDate
),
DayCount2 as
(
    Select d.[Day of Week], COUNT(*) 'WD COUNT'
    From DayCount1 d
    Group by d.[Day of Week]
),
Data2 as
(
Select d.[Record Date], 
    d.[Day of Week], 
    d.Category, 
    d.HourofDay
    , Count(*) 'Total Per Day', 
    t.[WD COUNT] 'Number of Days'

FROM Data d
Join DayCount2 d2 on d.[Day of Week] = d2.[Day of Week]
Group by d.[Record Date], d.DayWeekNum, d.[Day of Week],d2.[WD COUNT],d.Category, d.HourofDay
)

Select 
    d.[Day of Week]
    , d.Category
    , d.HourofDay
    , SUM(d.[Total Per Day]) 'Total Records During Hour'
    , MAX(d.[Total Per Day]) 'MAX per Hour'
    ,d.[Number of Days]
    , CAST(CAST(SUM(d.[Total Per Day]) as dec(8,2))/CAST(d.[Number of Days] as dec(8,2)) as dec(8,2)) 'Average'
From Data2 d
Where Category in ('A', 'B','C', 'D','E','F','G')
Group by d.[Day of Week], d.Category, d.HourofDay, d.[Number of Days]
Order by d.[Day of Week], d.Category, d.HourofDay

示例数据

MyTimeStamp            ,    Category
2017-10-31 08:50:53.600,    A
2017-10-31 08:49:43.837,    B
2017-10-31 08:49:36.547,    A
2017-10-31 08:49:19.130,    B
2017-10-31 08:47:47.360,    C
2017-10-31 08:47:33.230,    A
2017-10-31 08:47:00.157,    B
2017-10-31 08:41:57.553,    B
2017-10-31 08:41:16.960,    A
2017-10-31 08:39:27.940,    A

示例输出

Weekday Category    HourofDay   Rpt Cnt MIN MAX Average StDev
Friday      A       0           80      1   5   0.83    1.12
Friday      A       1           71      1   4   0.74    0.3
Friday      A       2           65      1   4   0.68    0.23
Friday      A       3           44      1   4   0.46    0.1
Friday      A       4           36      1   4   0.38    0.01
Friday      A       5           22      1   3   0.23    1.21
Friday      A       6           21      1   2   0.22    0.05
Friday      A       7           19      1   2   0.2     0.01
Friday      A       8           49      1   3   0.51    0.51
Friday      A       9           97      1   7   1.01    1.02
Friday      A       10          132     1   5   1.38    1.12
Friday      A       11          208     1   7   2.17    2

我保留了一个计数 table 作为我系统上的一个视图。这会生成 10,000 行零读取。这实际上比从持久性 table 存储和读取 10,000 行要快。我最初是从 Jeff Moden 那里了解到 tally tables 的。他在这里有一篇关于这个主题的优秀文章。 http://www.sqlservercentral.com/articles/T-SQL/62867/ 事实上,生成这个计数的代码 table 是他写的。我只是修改它,把它变成一个视图,这样我就不用一直写这个了。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO