每天都有错过的日子

时间:2018-01-29 10:37:15

标签: sql sql-server

我有一个带有以下结构和数据的SQL Server表:

Created              ,  keyword
'2017-10-03 19:18:00',  'test7'
'2017-10-07 01:06:00',  'test3'
'2017-10-07 15:19:00',  'test2'
'2017-10-07 21:39:00',  'test10'
'2017-10-08 00:36:00',  'test3'
'2017-10-08 01:26:00',  'test13'
'2017-10-08 01:33:00',  'test9'
'2017-10-08 08:23:00',  'test13'
'2017-10-08 09:35:00',  'test9'
'2017-10-08 12:38:00',  'test9'
'2017-10-08 15:07:00',  'test2'
'2017-10-10 05:09:00',  'test4'

我想运行一个计算活动的查询并按天分组,也计算没有记录任何内容的天数,并将这些天的活动显示为零。因此,我想要一个将返回以下结果集的查询:

'2017-10-03', 1
'2017-10-04', 0
'2017-10-05', 0
'2017-10-06', 0
'2017-10-07', 3
'2017-10-08', 7
'2017-10-09', 0
'2017-10-03', 1

我知道如何运行查询并将其按天数分组,但不知道如何记录未记录的天数。因为我是Sql的新手,如果有人可以提供一个有效的例子,我将非常感激。提前致谢

3 个答案:

答案 0 :(得分:2)

试试这个:

declare @startDate date = '2017-10-01'
declare @endDate date = '2017-10-31'

;with cte as (
select cast(@startDate as date) [dayOfYear]
union all
select DATEADD(day, 1, [dayOfYear]) from cte
where [dayOfYear] < @endDate
)

select dayOfYear, SUM(case when Created is null then 0 else 1 end) from cte
left join MY_TABLE [T] on cte.dayOfYear = CAST(T.Created as date)
group by dayOfYear

逻辑如下:

获取@startDate@endDate之间所有日期的表格(CTE - 我指定的是10月的第一个和最后一个)。然后我们离开加入你的表,当天没有匹配时,我们将相应的值定义为0,否则为1。然后它足以在一天之内总结这些价值。

答案 1 :(得分:0)

 declare @date int
 WITH CTE_DatesTable
AS
(
  SELECT CAST('20171003' as date) AS [date]
  UNION ALL
  SELECT   DATEADD(dd, 1, [date])
  FROM CTE_DatesTable
  WHERE DATEADD(dd, 1, [date]) <= '20171010'
)
SELECT [CalendarDate]=[date] into #DimDate   FROM CTE_DatesTable

OPTION (MAXRECURSION 0);

select * from #DimDate

这将创建一个日历表以与当前表连接以填补空白

答案 2 :(得分:0)

当您没有日历表时,这是一个解决方案:

select row_number() over(order by getdate()) - 1 as n
into #nums
from sys.columns cross join sys.columns c2;

declare @t table(Created datetime, keyword varchar(100));
insert into @t values
('2017-10-03 19:18:00',  'test7'),
('2017-10-07 01:06:00',  'test3'),
('2017-10-07 15:19:00',  'test2'),
('2017-10-07 21:39:00',  'test10'),
('2017-10-08 00:36:00',  'test3'),
('2017-10-08 01:26:00',  'test13'),
('2017-10-08 01:33:00',  'test9'),
('2017-10-08 08:23:00',  'test13'),
('2017-10-08 09:35:00',  'test9'),
('2017-10-08 12:38:00',  'test9'),
('2017-10-08 15:07:00',  'test2'),
('2017-10-10 05:09:00',  'test4')

declare @min_dt date, @max_dt date;
select @min_dt = min(Created), @max_dt = max(Created)
from @t;

with calendar as
(
select dateadd(day, n, @min_dt) as dt
from #nums
where dateadd(day, n, @min_dt) <= @max_dt
)

select c.dt, isnull(count(t.keyword), 0) as cnt
from calendar c left join @t t
        on c.dt = cast(t.Created as date)
group by c.dt; 

在我的情况下,我没有桌面日历,但我有固定的数字表(Nums),但是如果你没有数字表,你可以像在#nums中那样生成它(您应该将生成的数字限制为合理的数字)