SQL - 显示两个日期之间的所有日期

时间:2017-05-04 09:25:46

标签: sql sql-server tsql

我将以下数据保存为[OccuredAtUtc]中的日期,如下所示:

- 剧透警告:“2017-04-26”和“2017-04-29”丢失。

  

[OccuredAtUtc]中的原始日期:

2017-04-24 12:16:58.5080000
2017-04-24 18:11:53.3090000
2017-04-25 18:34:18.3090000
2017-04-27 20:42:28.8570000
2017-04-28 21:10:36.7070000
2016-04-28 10:37:57.5970000
2016-04-30 10:38:55.7010000
2016-04-30 10:48:19.0390000
2016-04-31 10:48:19.2990000
.
.
.

我有这个代码可以从两个间隔(上周)正确返回数据。

SELECT 
        [MessageType].[Name] AS [Channel],
        CONVERT(VARCHAR(11), [OccuredAtUtc], 106) AS [Time],
        COUNT(*) AS [Count]
FROM @table1
        INNER JOIN @table2 ON ... = ...
WHERE ( [OccuredAtUtc] > '2017-04-24'
        AND [OccuredAtUtc] < '2017-04-30' )
GROUP BY (CONVERT(VARCHAR(11), [OccuredAtUtc], 106)),
         [MessageType].[Name]
ORDER BY [Time] ASC

但是输出不会显示“2017年4月26日”和“2017年4月29日”的一行,因为这些天我的数据库中没有记录。

OLD OUTPUT:缺少第26个&amp; 4月29日。

[Channel]       [Time]          [Count]
------------------------------------
FTP           24 Apr 2017         7
HTTP          24 Apr 2017         9
FTP           25 Apr 2017         6
HTTP          25 Apr 2017         2
------MISSING 26 Apr--------
FTP           27 Apr 2017         56
HTTP          27 Apr 2017         12
FTP           28 Apr 2017         5
------MISSING 29 Apr--------
HTTP          28 Apr 2017         17
FTP           30 Apr 2017         156
HTTP          30 Apr 2017         19

我想显示错误日期的行,即使此时没有发生事件 ...

所以新的OUTPUT应该是这样的。

通缉输出:

[Channel]       [Time]          [Count]
------------------------------------
FTP             24 Apr 2017        7
HTTP            24 Apr 2017        9
FTP             25 Apr 2017        6
HTTP            25 Apr 2017        2
0               26 Apr 2017        0  -- here we go
FTP             27 Apr 2017        56
HTTP            27 Apr 2017        12
FTP             28 Apr 2017        5
HTTP            28 Apr 2017        17
0               29 Apr 2017        0  -- here we go
FTP             30 Apr 2017        156
HTTP            30 Apr 2017        19

我知道有像我这样的回答问题,我正在尝试重新制作代码,但我失败了。

SHOW ALL Dates data between two dates; if no row exists for particular date then show zero in all columns

How to generate all dates between two dates

3 个答案:

答案 0 :(得分:1)

与@ DhruvJoshi的答案类似,但使用递归CTE来生成日期:

DECLARE @MinDate DATE = '20170424',
        @MaxDate DATE = '20170430';

WITH allDates AS
(
    SELECT @MinDate AS dates

    UNION ALL

    SELECT DATEADD(DAY, 1, ad.[dates] )
    FROM allDates AS ad
    WHERE ad.[dates] < @MaxDate
)

SELECT 
        ISNULL([MessageType].[Name],0) AS [Channel],
        dates AS [Time],
        COUNT([MessageType].[Name]) AS [Count]
FROM 
(
   SELECT dates
   FROM allDates
) AS T
LEFT JOIN 
@table1 ON T.dates=CONVERT(VARCHAR(11), @table1.[OccuredAtUtc], 106)
        LEFT JOIN @table2 ON ... = ...
GROUP BY dates,
         [MessageType].[Name]
ORDER BY [Time] ASC

答案 1 :(得分:0)

您可以使用类似Tally表的内容生成特定时间间隔之间的所有日期。

SELECT 
        ISNULL([MessageType].[Name],0) AS [Channel],
        dates AS [Time],
        COUNT([MessageType].[Name]) AS [Count]
FROM 
(
   SELECT 
      TOP (DATEDIFF(d,'2017-04-24','2017-04-30')+1) 
       DATEADD(d,ROW_NUMBER() OVER( ORDER BY (SELECT 1))-1,'2017-04-24') dates
    FROM sys.objects a CROSS JOIN sys.objects b 
)T
LEFT JOIN 
@table1 ON T.dates=CONVERT(VARCHAR(11), @table1.[OccuredAtUtc], 106)
        LEFT JOIN @table2 ON ... = ...
AND ( [OccuredAtUtc] > '2017-04-24'
        AND [OccuredAtUtc] < '2017-04-30' )
GROUP BY dates,
         [MessageType].[Name]
ORDER BY [Time] ASC

有关Tally表格的更多说明,请阅读 this article

答案 2 :(得分:0)

declare @t table ( i int identity , b bit, d as dateadd (dd, i - 1, 0 ))

insert into @t (b)
VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0)

insert into @t (b)
select 0
from @t t1
cross apply ( select b from @t) as t2
cross apply ( select b from @t) as t3
cross apply ( select b from @t) as t4
cross apply ( select b from @t) as t5

select t.d, isnull(y.channel,0), count(y.[date])
from @t t
    left join yourtable y on y.[date] = t.d
where d between getdate() - 30 and getdate()
group by t.d, isnull(y.channel,0)