Reputation: 13
I need to create a patient census report that shows average number patients present per hour and per day of a week over a given time period. This would allow me to show, for example, over the last 6 months there was an average of 4 people in the ER on Mondays. I have a table valued function that will show the following for patients: VisitID, FromDateTime, ThruDateTime, LocationID.
I was able to show the number of patients in, for example, the ER for a given day using the code below. But it is limited to one day only. (Adapted from http://www.sqlservercentral.com/Forums/Topic939818-338-1.aspx).
--Census Count by Date Range--
DECLARE @BeginDateParameter DateTime, @EndDateParameter DateTime
SET @BeginDateParameter = '20160201'
SET @EndDateParameter = '2016-02-01 23:59:59.000'
----------------------------------------------------
-- Create a temp table to hold the necessary values
-- plus an extra "x" field to track processing
----------------------------------------------------
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL DROP TABLE #Temp
CREATE TABLE #Temp (ID INT Identity NOT NULL, VisitID VarChar(100), SourceID VarChar(100),
FromDateTime DateTime, ThruDateTime DateTime, x INT)
----------------------------------------------------
-- Populate the temp table with values from the
-- the actual table in the database
----------------------------------------------------
INSERT INTO #Temp
SELECT VisitID, FromDateTime, ThruDateTime
FROM PatientFlowTable(BeginDateParameter,@EndDateParameter)
WHERE (FromDateTime BETWEEN @BeginDateParameter AND @EndDateParameter +1
OR ThruDateTime BETWEEN @BeginDateParameter AND @EndDateParameter +1)
AND LocationID = 'ER'
-- Given Period is taken as inclusive of given hours in the input (eg. 15:25:30 will be taken as 15:00:00)
-- frist make sure that the minutes, seconds and milliseconds are removed from input range for clarity
set @BeginDateParameter = dateadd(hh, datepart(hh,@BeginDateParameter), convert(varchar(12),@BeginDateParameter,112))
set @EndDateParameter = dateadd(hh, datepart(hh,@EndDateParameter), convert(varchar(12),@EndDateParameter,112))
-- you may create this CTE by other ways (eg. from permanent Tally table)...
;with dh
as
(
select top 24
DATEADD(hour,ROW_NUMBER() OVER (ORDER BY [Object_id])-1,convert(varchar(12),@BeginDateParameter,112)) as HoDstart
,DATEADD(hour,ROW_NUMBER() OVER (ORDER BY [Object_id]),convert(varchar(12),@BeginDateParameter,112)) as HoDend
,ROW_NUMBER() OVER (ORDER BY Object_id)-1 as DayHour
from sys.columns -- or any other (not very big) table which have more than 24 raws, just remamber to change
-- [Object_id] in OVER (ORDER BY [Object_id]... to some existing column
)
select d.DayHour, count(w.VisitID) as PatientCount
from dh d
left join #Temp w
on w.[FromDateTime] < d.HoDend
and w.[ThruDateTime] >= d.HoDstart
where d.HoDstart between @BeginDateParameter and @EndDateParameter
group by d.DayHour
order by d.DayHour
SELECT VisitID, FromDateTime, ThruDateTime
FROM PatientFlowTable(BeginDateParameter,@EndDateParameter)
WHERE (FromDateTime BETWEEN @BeginDateParameter AND @EndDateParameter +1
OR ThruDateTime BETWEEN @BeginDateParameter AND @EndDateParameter +1)
AND LocationID = 'ER'
Output example for the first three hours show patients that were present in the ER by taking into account their departure time.
Hour PatientCount
0 2
1 3
2 3
Upvotes: 0
Views: 389
Reputation: 169
For querying short time periods, I would create a table-valued function that generates the hour entries. The results table can be joined into your query.
CREATE FUNCTION [dbo].[f_hours] (@startDateTime DATETIME,
@endDateTime DATETIME)
RETURNS @result TABLE (
[dateTime] DATETIME PRIMARY KEY
)
AS
BEGIN
DECLARE
@dateTime DATETIME = @startDateTime,
@hours INT = DATEDIFF(hour, @startDateTime, @endDateTime)
WHILE (@dateTime <= @endDateTime)
BEGIN
INSERT
INTO @result
VALUES (@dateTime)
SET @dateTime = DATEADD(hour, 1, @dateTime)
END
RETURN
END
GO
The time required by the function can be output with SET STATISTICS TIME ON. For the generation of over 6000 records needs my computer 53 ms.
SET STATISTICS TIME ON
SELECT *
FROM [dbo].[f_hours]('2016-02-01', '2016-02-10 16:00')
SET STATISTICS TIME OFF
Upvotes: 2