我想在过去24小时内为我的数据集创建一个图表。
我找到了一个有效的解决方案,但这非常糟糕,因为我在外面加入数据库中的每一行,因为我使用的是(现已弃用)"所有"组中的参数。
这是目前有效的解决方案。 首先,我宣布从现在起24小时后的日期间隔。我宣布它两次,所以我可以在以后的程序中使用它。
Declare @StartDate datetime = dateadd(hour, -24, getdate())
Declare @StartDateProc datetime = dateadd(hour, -24, getdate())
Declare @EndDate datetime = getdate()
我将日期填充到临时表中,包括一个特殊的格式化日期。
create table #tempTable
(
Date datetime,
DateString varchar(11)
)
while @StartDate <= @EndDate
begin
insert into #tempTable (Date, DateString)
values (@StartDate, convert(varchar(8), @StartDate, 5) + '-' + convert(varchar(2), @StartDate, 108));
SET @StartDate = dateadd(hour,1, @StartDate);
end
这给了我这样的数据:
Date DateString
---------------------------------------------
2015-12-09 13:59:01.970 09-12-15-13
2015-12-09 14:59:01.970 09-12-15-14
2015-12-09 15:59:01.970 09-12-15-15
2015-12-09 16:59:01.970 09-12-15-16
所以我想要的是在匹配日期字符串上加入我的数据集并显示日期,即使匹配的行为零。
以下是查询的其余部分
select
Date = c.Date,
Amount = sum(c.Amount)
from
DbTable a
outer apply
(select
Date = b.DateString,
Amount = count(*)
from
#tempTable b
where
convert(varchar(8), a.DateColumn, 5) + '-' + convert(varchar(2), a.DateColumn, 108) = b.DateString
group by all
b.DateString) c
where
a.SomeParameter = 'test' and
a.DateColumn >= @StartDateProc and
a.DateColumn <= @EndDate
group by
c.Date
drop table #tempTable
测试以显示实际数据:
Declare @StartDate datetime = dateadd(hour, -24, getdate())
Declare @EndDate datetime = getdate()
select
dateString = convert(varchar(8),a.DateColumn,5) + '-' + convert(varchar(2),a.DateColumn, 108),
Amount = COUNT(*)
from
DbTable a
where
a.someParameter = 'test' and
a.DateColumn>= dateadd(hour, -24, getdate()) and
a.DateColumn<= getdate()
group by
convert(varchar(8),a.DateColumn,5) + '-' + convert(varchar(2),a.DateColumn, 108)
第一行输出:
dateString Amount
09-12-15-14 1
09-12-15-15 1
09-12-15-16 1
09-12-15-17 3
09-12-15-18 1
09-12-15-22 3
09-12-15-23 2
正如您在此处所见,从19.00到21.00的时间没有数据。这就是我想要显示数据的方式:
dateString Amount
09-12-15-14 1
09-12-15-15 1
09-12-15-16 1
09-12-15-17 3
09-12-15-18 1
09-12-15-19 0
09-12-15-20 0
09-12-15-21 0
09-12-15-22 3
09-12-15-23 2
答案 0 :(得分:3)
通常情况下,这将使用left join
而不是outer apply
。逻辑很简单:保留第一个表中的所有行以及第二个表中的任何匹配信息。这意味着将日期表放在第一位:
select tt.DateString, count(t.DateColumn) as Amount
from #tempTable tt left join
DbTable t
on convert(varchar(8), t.DateColumn, 5) + '-' + convert(varchar(2), t.DateColumn, 108) = tt.DateString and
t.SomeParameter = 'test'
where tt.Date >= @StartDateProc and
tt.Date <= @EndDate
group by tt.DateString;
此外,您对日期的比较似乎过于复杂,但如果它对您有效,则可行。
答案 1 :(得分:0)
这里最好的选择是使用DATETIME
类型本身而不是失去使用索引的机会:
Declare @d datetime = GETDATE()
;WITH cte1 AS(SELECT TOP 25 -1 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) h
FROM master..spt_values),
cte2 AS(SELECT DATEADD(hh, -h, @d) AS startdate,
DATEADD(hh, -h + 1, @d) AS enddate
FROM cte1)
SELECT c.startdate, c.enddate, count(*) as amount
FROM cte2 c
LEFT JOIN DbTable a ON a.DateColumn >= c.startdate AND
a.DateColumn < c.enddate AND
a.SomeParameter = 'test'
GROUP BY c.startdate, c.enddate