Reputation: 6122
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
I am trying to get a count of @child.childvalue every day, every hour, so there would be 8760 rows in my result. First pass had a loop and a CONVERT which takes ~5 minutes to run with the actual result set (this is just a sample for illustation). I did create a CTE to make a calendar temp table (using http://www.sqlpointers.com/2006/07/generating-temporary-calendar-tables.html), and thought it could be joined somehow to add "empty values" into the result set.
I need to get a result set that looks like this
date hour count
...
2011-09-17 0 0
....
2011-09-17 12 2
....
2011-10-11 12 1
How can that be done efficiently?
Thanks.
Upvotes: 0
Views: 1153
Reputation: 6205
try this.
;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)
Upvotes: 1
Reputation: 20320
Something like (have childvalue in your query but not in your example result?)
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
Note Date type was introduced in SQL 2008
Upvotes: 1