Retrospective Reporting

  • I have been posed a question, and I have a solution that is a little too manual for my liking! Can anyone help me produce a query that will do the following in a single query?

    We have a table that stores data of people we come into contact with and I need to produce a summary report for the people in custody in 30 minute intervals from 15:30 06/12/2007 until 10:00 24/12/2007. I can do it using the following query, but changing the EndTime and StartTime to all of the intervals in the above time:

    SELECT unit.Surname_Cache AS 'Custody Unit', COUNT(*) AS 'Detainee count'

    FROM TBL_GPPCustodyEvent event WITH(NOLOCK)

    LEFT JOIN TBL_GPerson unit WITH(NOLOCK) ON event.GPPCAUnit_RId = unit.Id

    WHERE event.EndTime > '2007-12-06 15:30'

    AND event.StartTime < '2007-12-06 15:30'

    GROUP BY event.GPPCAUnit_RId, unit.Surname_Cache

    ORDER BY unit.Surname_Cache

    Is there a method to complete the report in one query?

    Any help will be appreciated.

    Regards,

    Phil

    PS As part of the select it would have to show the date & time being queried so that the report made sense! I.e. 2007-12-06 15:30 etc.

    Regards,

    Phil

  • I'm not sure if anyone is interested, but I have a solution (not the most elegant no doubt). Feel free to post comments - I like to learn better ways of working.

    Cheers,

    Phil

    Solution:

    -- CREATE TEMP TABLES TO BUILD DATES

    USE TempDB

    GO

    CREATE TABLE [dbo].[#Hours](

    [Hour] [varchar](50) COLLATE Latin1_General_CI_AS NULL

    )

    INSERT INTO #Hours (Hour)

    SELECT '00' UNION ALL

    SELECT '01' UNION ALL

    SELECT '02' UNION ALL

    SELECT '03' UNION ALL

    SELECT '04' UNION ALL

    SELECT '05' UNION ALL

    SELECT '06' UNION ALL

    SELECT '07' UNION ALl

    SELECT '08' UNION ALL

    SELECT '09' UNION ALL

    SELECT '10' UNION ALL

    SELECT '11' UNION ALL

    SELECT '12' UNION ALL

    SELECT '13' UNION ALL

    SELECT '14' UNION ALL

    SELECT '15' UNION ALL

    SELECT '16' UNION ALL

    SELECT '17' UNION ALL

    SELECT '18' UNION ALL

    SELECT '19' UNION ALL

    SELECT '20' UNION ALL

    SELECT '21' UNION ALL

    SELECT '22' UNION ALL

    SELECT '23'

    CREATE TABLE [dbo].[#Mins](

    [Min] [varchar](50) COLLATE Latin1_General_CI_AS NULL

    )

    INSERT INTO #Mins

    SELECT '00' UNION ALL

    SELECT '30'

    CREATE TABLE [dbo].[#Days](

    [Day] [varchar](50) COLLATE Latin1_General_CI_AS NULL

    )

    INSERT INTO #Days

    SELECT '06' UNION ALL

    SELECT '07' UNION ALl

    SELECT '08' UNION ALL

    SELECT '09' UNION ALL

    SELECT '10' UNION ALL

    SELECT '11' UNION ALL

    SELECT '12' UNION ALL

    SELECT '13' UNION ALL

    SELECT '14' UNION ALL

    SELECT '15' UNION ALL

    SELECT '16' UNION ALL

    SELECT '17' UNION ALL

    SELECT '18' UNION ALL

    SELECT '19' UNION ALL

    SELECT '20' UNION ALL

    SELECT '21' UNION ALL

    SELECT '22' UNION ALL

    SELECT '23' UNION ALL

    SELECT '24'

    -- CREATE TEMP DATE TABLE

    CREATE TABLE [dbo].[#DateAndTime] (

    [DateAndTime] [datetime]

    )

    -- POPULATE TEMP TABLE

    INSERT INTO #DateAndTime

    SELECT CAST('2007-12-' + [Day] + ' ' + [Hour] + ':' + [Min] AS datetime)

    FROM #Hours, #Mins, #Days

    USE NicheLive

    GO

    SELECT DateAndTime AS 'Time', unit.Surname_Cache AS 'Custody Unit', COUNT(*) AS 'Detainee count'

    FROM TBL_GPPCustodyEvent event WITH(NOLOCK)

    LEFT JOIN TBL_GPerson unit WITH(NOLOCK) ON event.GPPCAUnit_RId = unit.Id,

    #DateAndTime

    WHEREevent.StartTime < DateAndTime

    ANDevent.EndTime > DateAndTime

    GROUP BY DateAndTime, event.GPPCAUnit_RId, unit.Surname_Cache

    ORDER BY DateAndTime, unit.Surname_Cache

    -- DROP TEMP TABLES

    DROP TABLE #Hours

    GO

    DROP TABLE #Mins

    GO

    DROP TABLE #Days

    GO

    DROP TABLE #DateAndTime

    GO

    Regards,

    Phil

  • Your solution looks like the best way to handle that particular problem but I would make 2 changes.

    Instead of creating a temporary table each time you run the report I would create a perm table with an indexed datetime field. For a 20 year period it would only hold around 35,000 rows which won't take up very much space and since its indexed will probably speed your query up dramatically over creating a temp table each time.

    The only other change I would make is to make either (or both) your > or = or <=. Or consider using a between.

    DateAndTime BETWEEN event.EndTime and event.StartTime

    Currently if the StartTime or EndTime is exactly 00 or 30 that row will never be counted. It won't happen very often what with milliseconds being counted but even if it happens once it will be a pain to figure out what went wrong.

    Kenneth

    Kenneth FisherI was once offered a wizards hat but it got in the way of my dunce cap.--------------------------------------------------------------------------------For better, quicker answers on T-SQL questions, click on the following... http://www.sqlservercentral.com/articles/Best+Practices/61537/[/url]For better answers on performance questions, click on the following... http://www.sqlservercentral.com/articles/SQLServerCentral/66909/[/url]Link to my Blog Post --> www.SQLStudies.com[/url]

  • Thank you for your feedback, I appreciate all the help I get from this site and I am particularly impressed by (a) the speed in which I have had responses in the past and (b) the impressive amount of knowledge people have with SQL Server and T-SQL.

    Regards,

    Phil

    Regards,

    Phil

Viewing 4 posts - 1 through 3 (of 3 total)

You must be logged in to reply to this topic. Login to reply