每日每小时查询的SQL Server拆分日期时间?

时间:2012-09-27 16:58:14

标签: sql-server-2008 group-by aggregate-functions

SQL Server 2008。

declare @pardate table ( pardateid int, pardatewhen datetime2(3) )
insert into @pardate values ( 1 , '2011-09-17 12:43' )
insert into @pardate values ( 2 , '2011-09-17 12:44' )
insert into @pardate values ( 3 , '2011-10-11 12:45' )
insert into @pardate values ( 4 , '2011-10-12 12:46' )
insert into @pardate values ( 5 , '2011-10-13 12:47' )
insert into @pardate values ( 6 , '2011-11-20 12:48' )
insert into @pardate values ( 7 , '2011-11-21 12:49' )
insert into @pardate values ( 8 , '2011-11-22 12:50' )
declare @child table ( childid int , pardateid int , childvalue char(6) )
insert into @child values ( 1 , 1 , 'aaaaaa' )
insert into @child values ( 2 , 2 , 'bbbbbb' )
insert into @child values ( 3 , 3 , 'cccccc' )
insert into @child values ( 4 , 4 , 'dddddd' )
insert into @child values ( 5 , 5 , 'cccccc' )
insert into @child values ( 6 , 6 , 'cccccc' )
insert into @child values ( 7 , 7 , 'eeeeee' )
insert into @child values ( 8 , 8 , 'ffffff' )

select pardatewhen , childvalue , COUNT(childvalue)
from @child childtable join @pardate parenttable on childtable.pardateid=parenttable.pardateid
group by pardatewhen , childvalue

我想每天每小时都计算一次@ child.childvalue,所以我的结果会有8760行。 第一遍有一个循环和一个CONVERT,用实际的结果集运行大约需要5分钟(这只是插图的一个例子)。我确实创建了一个CTE来制作一个日历临时表(使用http://www.sqlpointers.com/2006/07/generating-temporary-calendar-tables.html),并认为它可以以某种方式加入到结果集中添加“空值”。

我需要得到一个看起来像这样的结果集

date          hour    count
...
2011-09-17    0       0
....
2011-09-17    12      2
....
2011-10-11    12      1

如何才能有效地完成?

感谢。

2 个答案:

答案 0 :(得分:1)

类似的东西(在您的查询中有子值,但在示例结果中却没有?)

select Cast(pardatewhen as Date) as [date], DatePart(hour,pardatewhen) as [hour] , childvalue , COUNT(childvalue) 
from @child childtable 
join @pardate parenttable on childtable.pardateid=parenttable.pardateid 
group by Cast(pardatewhen as Date), DatePart(hour,pardatewhen), childvalue 

注意SQL 2008中引入了日期类型

答案 1 :(得分:1)

试试这个。

;WITH cal AS
(SELECT CAST('2011-01-01' AS DATETIME) AS cal_date
  UNION ALL
 SELECT DATEADD(hour,1,cal_date)
  FROM cal
  WHERE cal_date < '2011-12-31 23:00'
)  
, par AS
(
    select CAST(pardatewhen AS DATE) AS pardate, DATEPART(hh,pardatewhen) AS parhour , COUNT(childvalue) as num
    from @child childtable 
    join @pardate parenttable on childtable.pardateid=parenttable.pardateid 
    group by CAST(pardatewhen AS DATE), DATEPART(hh,pardatewhen)  
)
SELECT CAST(cal.cal_date  AS DATE) AS [date],DATEPART(hh,cal.cal_date) AS [hour],ISNULL(par.num,0) AS [childvalue_count]
FROM    cal  
LEFT JOIN par
    ON CAST(cal.cal_date  AS DATE) = par.pardate
        AND DATEPART(hh,cal.cal_date) = par.parhour
OPTION (MAXRECURSION 9999)