Sql 以天为单位分组
我有一个sql server表,其结构和数据如下:Sql 以天为单位分组,sql,sql-server,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
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新手,如果有人能提供一个工作示例,我将不胜感激。提前谢谢
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
这将创建一个日历表与当前表连接,以填补空白
这将创建一个日历表,以便与当前表连接以填补空白尝试以下操作:
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
逻辑如下:
获取CTE-I指定的10月1日和10月最后一日@startDate和@endDate之间的所有日期的表格。然后我们离开join表,当天数不匹配时,我们将相应的值定义为0,否则定义为1。然后,每天对这些值求和就足够了。试试这个:
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
逻辑如下:
获取CTE-I指定的10月1日和10月最后一日@startDate和@endDate之间的所有日期的表格。然后我们离开join表,当天数不匹配时,我们将相应的值定义为0,否则定义为1。然后,每天对这些值求和就足够了。当您没有日历表时,这里有一个解决方案:
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中一样生成它,您应该将生成的数字限制为合理的数字当您没有日历表格时,这里有一个解决方案:
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中一样生成它,您应该将生成的数字限制在合理的数字上最好的解决方案是创建表格日历,将您的表加入此日历表lrft在dt=dt和dt之间加入您的表。。。并对结果进行分组。如果您没有日历表,您可以根据以前使用另一个DBMS的经验快速生成它,我认为没有简单的解决方案。也许最好的方法是循环查询的输出并手动填补空白。谢谢,您可以提供一个示例吗?类似的问题最好的解决方案是创建一个表日历,将您的表连接到此日历表lrft在dt=dt和dt之间连接您的表。。。并对结果进行分组。如果您没有日历表,您可以根据以前使用另一个DBMS的经验快速生成它,我认为没有简单的解决方案。也许最好是循环查询的输出并手动填补空白。谢谢,您可以提供一个示例吗?类似的问题如果您有100多行,则必须添加“OPTION MAXRECURSION 200”。这将阻止:语句终止。在语句完成之前,最大递归100已用尽。如果有100多行,则必须添加“OPTION MAXRECURSION 200”。这将阻止:语句终止。在语句完成之前,已耗尽最大递归100。