Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Average Daily Census

Posted on 2015-01-23
12
76 Views
Last Modified: 2015-12-05
I have records that have start and end dates, denoting a clients' length of stay.  Say client 1 started on 1/2/2015 and ended on 1/5/2015.  Client 2 started 1/3/2015 and ended 1/6/2015, client 3 started... etc...
I need to report census by day:
1/1/2015 - 0
1/2/2015 - 1
1/3/2015 - 2
etc...

What is the cleanest way to do this.  I am using SQL Server 2008 r2.
0
Comment
Question by:UniqueData
  • 5
  • 3
  • 3
  • +1
12 Comments
 
LVL 92

Accepted Solution

by:
Patrick Matthews earned 500 total points
ID: 40566863
A "calendar" is best for something like this:

CREATE TABLE tblPatientStays (ID int identity(1, 1), PatientID int, StayStart datetime, StayEnd datetime)

INSERT INTO tblPatientStays (PatientID, StayStart, StayEnd) VALUES
    (1, '2015-01-02', '2015-01-05'),
    (2, '2015-01-04', '2015-01-10')

CREATE TABLE tblCalendar(Dt datetime)

INSERT INTO tblCalendar (Dt) VALUES
    ('2015-01-01'),
    ('2015-01-02'),
    ('2015-01-03'),
    ('2015-01-04'),
    ('2015-01-05'),
    ('2015-01-06'),
    ('2015-01-07'),
    ('2015-01-08'),
    ('2015-01-09'),
    ('2015-01-10'),
    ('2015-01-11'),
    ('2015-01-12'),
    ('2015-01-13'),
    ('2015-01-14'),
    ('2015-01-15'),
    ('2015-01-16'),
    ('2015-01-17'),
    ('2015-01-18'),
    ('2015-01-19'),
    ('2015-01-20'),
    ('2015-01-21'),
    ('2015-01-22'),
    ('2015-01-23'),
    ('2015-01-24'),
    ('2015-01-25'),
    ('2015-01-26'),
    ('2015-01-27'),
    ('2015-01-28'),
    ('2015-01-29'),
    ('2015-01-30'),
    ('2015-01-31')
    
SELECT c.Dt, COUNT(p.PatientID) AS NumPatients
FROM tblCalendar c LEFT JOIN
    tblPatientStays p ON c.Dt >= p.StayStart AND c.Dt <= p.StayEnd
GROUP BY c.Dt
ORDER BY c.Dt

DROP TABLE tblCalendar
DROP TABLE tblPatientStays

Open in new window

0
 
LVL 92

Expert Comment

by:Patrick Matthews
ID: 40566931
There is also a quick and dirty method that exploits one of the system tables, but the calendar table approach is definitely better.

CREATE TABLE tblPatientStays (ID int identity(1, 1), PatientID int, StayStart datetime, StayEnd datetime)

INSERT INTO tblPatientStays (PatientID, StayStart, StayEnd) VALUES
    (1, '2015-01-02', '2015-01-05'),
    (2, '2015-01-04', '2015-01-10')

SELECT c.Dt, COUNT(p.PatientID) AS NumPatients
FROM (
    SELECT DATEADD(day, number, '2015-01-01') AS Dt
    FROM master..spt_values
    WHERE Type = 'P' AND number < 31) c LEFT JOIN
    tblPatientStays p ON c.Dt >= p.StayStart AND c.Dt <= p.StayEnd
GROUP BY c.Dt
ORDER BY c.Dt

DROP TABLE tblPatientStays

Open in new window

0
 
LVL 7

Author Comment

by:UniqueData
ID: 40566951
What is wrong with the second option?  Why is the first better?  The reason I ask is I am going to run this for a full year (or possibly more). Although I don't quite understand what is happening :)  the second looks cleaner and you don't seem to hard code any dates.
0
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

 
LVL 7

Author Comment

by:UniqueData
ID: 40566982
Ah, I see.  That system table just has values when type = 'P'.  So I would have to adjust the 'where < 32 ' depending on the number of days in each month
0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 40567000
If you have two known dates, just use DATEDIFF.  Absolutely no reason to waste resource using a calendar table and aggregation of top of it for that:

SELECT ..., DATEDIFF(DAY, start_date, end_date) + 1 AS total_stay_in_days, ...
FROM ...
0
 
LVL 7

Author Comment

by:UniqueData
ID: 40567033
Sorry Scott, Patrick is on the right track as that is how they currently calculate average daily census by month.  Getting length of stay alone and averaging will only get you average length of stay, not daily/monthly averages.

But Patrick, any ideas on how to span multiple months or if a client's stay goes over two months?
0
 
LVL 7

Author Comment

by:UniqueData
ID: 40567077
I was able to tweak Patrick's code to make it a little more flexible, but not sure how to handle multiple months...

CREATE TABLE tblPatientStays (ID int identity(1, 1), PatientID int, StayStart datetime, StayEnd datetime)

INSERT INTO tblPatientStays (PatientID, StayStart, StayEnd) VALUES
    (1, '2015-01-02', '2015-02-05'),
    (2, '2015-01-04', '2015-01-10')
--Get First of month: DATEADD(month, DATEDIFF(month, 0, @mydate), 0)  
SELECT c.Dt, COUNT(p.PatientID) AS NumPatients
FROM (
    SELECT DATEADD(day, number, DATEADD(month, DATEDIFF(month,0,(Select Min(StayStart) From tblPatientStays)), 0)) AS Dt
    FROM master..spt_values
    WHERE Type = 'P' 
			AND number < DatePart(day,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,(Select Min(StayStart) From tblPatientStays))+1,0)))
	) c LEFT JOIN
    tblPatientStays p ON c.Dt between p.StayStart AND p.StayEnd
GROUP BY c.Dt
ORDER BY c.Dt

DROP TABLE tblPatientStays

Open in new window

0
 
LVL 50

Expert Comment

by:Lowfatspread
ID: 40567094
"its quick and dirty"

it uses a system table that in the end you have no control over,

that means it could change as the result of any patch/fix and version release....
or your use of it could start to impact system performance....

for a quick one-off test in a development system , its a quick trick dba's sometimes use to look at things with...

as production level code its better to implement your own solutions ....
0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 40567096
A tally table is still perfectly fine.  You don't need a "calendar" table for this.
0
 
LVL 92

Expert Comment

by:Patrick Matthews
ID: 40567231
The problem with the spt_values approach is that it's kind of a "hidden" feature: not documented, and there is always the possibility that Microsoft kills it in a future release.  Also, you're limited to 2047 items, so you couldn't use this to generate, say, a daily calendar over 10 years.
0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 40567298
You can also have  permissions issues if the user running the code isn't allowed to read the *master*.dbo.spt_values table.
0
 
LVL 7

Author Comment

by:UniqueData
ID: 40587987
I still don't undersrtand how I can handle multiple months.
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
MS SQL Delete Query 9 37
Better way to make a query with date filter. 5 36
length of the password hash sha1:64000 to set sql field property. 13 66
Negative isnull? 3 15
If you have heard of RFC822 date formats, they can be quite a challenge in SQL Server. RFC822 is an Internet standard format for email message headers, including all dates within those headers. The RFC822 protocols are available in detail at:   ht…
Ever needed a SQL 2008 Database replicated/mirrored/log shipped on another server but you can't take the downtime inflicted by initial snapshot or disconnect while T-logs are restored or mirror applied? You can use SQL Server Initialize from Backup…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question