We are building a query to count the number of events per hour, per day. Most days there are hours that do not have any activity and therefore where the query is run the cou
First I created a table function based on the recursive common table query described by Dave Markle (thanks for showing me this Dave!). This is extremely sweet because I only have to make the function once and I can use it for analysing any intervals.
if exists (select * from dbo.sysobjects where name = 'fn_daterange') drop function fn_daterange;
go
create function fn_daterange
(
@MinDate as datetime,
@MaxDate as datetime,
@intval as datetime
)
returns table
--**************************************************************************
-- Procedure: fn_daterange()
-- Author: Ron Savage
-- Date: 12/16/2008
--
-- Description:
-- This function takes a starting and ending date and an interval, then
-- returns a table of all the dates in that range at the specified interval.
--
-- Change History:
-- Date Init. Description
-- 12/16/2008 RS Created.
-- **************************************************************************
as
return
WITH times (startdate, enddate, intervl) AS
(
SELECT @MinDate as startdate, @MinDate + @intval - .0000001 as enddate, @intval as intervl
UNION ALL
SELECT startdate + intervl as startdate, enddate + intervl as enddate, intervl as intervl
FROM times
WHERE startdate + intervl <= @MaxDate
)
select startdate, enddate from times;
go
So if you do a select from that function all by itself you get a table of time intervals like this:
fn_daterange('12/14/2008 10:00:00', '12/14/2008 20:00:00', '01:00:00' )
returns:
startdate enddate intervl
----------------------- ----------------------- -----------------------
2008-12-14 10:00:00.000 2008-12-14 10:59:59.997 1900-01-01 01:00:00.000
2008-12-14 11:00:00.000 2008-12-14 11:59:59.997 1900-01-01 01:00:00.000
2008-12-14 12:00:00.000 2008-12-14 12:59:59.997 1900-01-01 01:00:00.000
2008-12-14 13:00:00.000 2008-12-14 13:59:59.997 1900-01-01 01:00:00.000
2008-12-14 14:00:00.000 2008-12-14 14:59:59.997 1900-01-01 01:00:00.000
2008-12-14 15:00:00.000 2008-12-14 15:59:59.997 1900-01-01 01:00:00.000
2008-12-14 16:00:00.000 2008-12-14 16:59:59.997 1900-01-01 01:00:00.000
2008-12-14 17:00:00.000 2008-12-14 17:59:59.997 1900-01-01 01:00:00.000
2008-12-14 18:00:00.000 2008-12-14 18:59:59.997 1900-01-01 01:00:00.000
2008-12-14 19:00:00.000 2008-12-14 19:59:59.997 1900-01-01 01:00:00.000
2008-12-14 20:00:00.000 2008-12-14 20:59:59.997 1900-01-01 01:00:00.000
Then I made a sample table of event data:
eventdate eventnote
----------------------- --------------------
2008-12-14 10:01:00.000 oo! an event!
2008-12-14 10:01:00.000 oo! an event!
2008-12-14 10:01:00.000 oo! an event!
2008-12-14 10:01:00.000 oo! an event!
2008-12-14 10:23:00.000 oo! an event!
2008-12-14 10:23:00.000 oo! an event!
2008-12-14 10:23:00.000 oo! an event!
2008-12-14 11:23:00.000 oo! an event!
2008-12-14 11:23:00.000 oo! an event!
2008-12-14 11:23:00.000 oo! an event!
2008-12-14 11:23:00.000 oo! an event!
2008-12-14 11:23:00.000 oo! an event!
2008-12-14 14:23:00.000 oo! an event!
2008-12-14 14:23:00.000 oo! an event!
2008-12-14 14:23:00.000 oo! an event!
2008-12-14 19:23:00.000 oo! an event!
2008-12-14 19:23:00.000 oo! an event!
2008-12-14 19:23:00.000 oo! an event!
2008-12-14 19:23:00.000 oo! an event!
2008-12-14 19:00:00.000 oo! an event!
2008-12-14 19:00:00.000 oo! an event!
2008-12-14 19:00:00.000 oo! an event!
22 Row(s) affected
Then I hooked them together with a LEFT OUTER JOIN like so:
select
dr.startdate,
dr.enddate,
count(me.eventdate) as eventcount
from
fn_daterange('12/14/2008 10:00:00', '12/14/2008 20:00:00', '01:00:00' ) dr
LEFT OUTER JOIN myevents me
on ( me.eventdate between dr.startdate and dr.enddate)
group by
dr.startdate,
dr.enddate
startdate enddate eventcount
----------------------- ----------------------- ----------
2008-12-14 10:00:00.000 2008-12-14 10:59:59.993 7
2008-12-14 11:00:00.000 2008-12-14 11:59:59.993 5
2008-12-14 12:00:00.000 2008-12-14 12:59:59.993 0
2008-12-14 13:00:00.000 2008-12-14 13:59:59.993 0
2008-12-14 14:00:00.000 2008-12-14 14:59:59.993 3
2008-12-14 15:00:00.000 2008-12-14 15:59:59.993 0
2008-12-14 16:00:00.000 2008-12-14 16:59:59.993 0
2008-12-14 17:00:00.000 2008-12-14 17:59:59.993 0
2008-12-14 18:00:00.000 2008-12-14 18:59:59.993 0
2008-12-14 19:00:00.000 2008-12-14 19:59:59.993 7
2008-12-14 20:00:00.000 2008-12-14 20:59:59.993 0
11 Row(s) affected
HOLY CRAP that is sweet - I can use this for all kinds of analysis at work! :-)
Thanks Fred for the question and Dave for the info on common table queries!
Ron