Calculating the throughput time

  • I am trying to calculate the throughput time, I have patient arrive time in one temp table and exit time in other temp table. The patient can have more than one appointment during the day, and we need to match up the arrive time with the first exit time after the arrive time.

    Possible cases:

    Arrive, --

    Arrive, Exit

    Arrive, Arrive, Exit

    Arrive, Exit, Arrive, Exit ???????

    Arrive, Exit, Arrive, --

    The problem is the event we using for exit time can occur more than one times.

    I can not figure out how to do the case like Arrive, Exit, ARRIVE, EXIT for 2nd appointment.

    I have 2 temp tables that have the following values.

    --===== If the test table already exists, drop it

    IF OBJECT_ID('TempDB.dbo.#Arrive','U') IS NOT NULL

    DROP TABLE #Arrive

    --===== If the test table already exists, drop it

    IF OBJECT_ID('TempDB.dbo.#Exit','U') IS NOT NULL

    DROP TABLE #Exit

    --===== Create the test table with

    CREATE TABLE #Arrive

    (

    ArriveID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,

    PatientID INT,

    ArriveTime DATETIME

    )

    --===== Create the test table with

    CREATE TABLE #Exit

    (

    ExitID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,

    PatientID INT,

    ExitTime DATETIME

    )

    ----===== All Inserts into the IDENTITY column

    --SET IDENTITY_INSERT #Arrive ON

    --===== Insert the test data into the test table

    INSERT INTO #Arrive

    (PatientID, ArriveTime)

    SELECT 100,'Oct 17 2007 08:00AM' UNION ALL

    SELECT 200,'Oct 17 2007 08:15AM' UNION ALL

    SELECT 200,'Oct 17 2007 10:30AM' UNION ALL

    SELECT 300,'Oct 17 2007 08:15AM' UNION ALL

    SELECT 300,'Oct 17 2007 11:30AM' UNION ALL

    SELECT 400,'Oct 17 2007 08:10AM' UNION ALL

    SELECT 500,'Oct 17 2007 08:00AM' UNION ALL

    SELECT 700,'Oct 17 2007 09:00AM' UNION ALL

    SELECT 700,'Oct 17 2007 11:00AM' UNION ALL

    SELECT 800,'Oct 17 2007 09:15AM'

    ----===== All Inserts into the IDENTITY column

    --SET IDENTITY_INSERT #Exit ON

    --===== Insert the test data into the test table

    INSERT INTO #Exit

    (PatientID, ExitTime)

    SELECT 100,'Oct 17 2007 09:00AM' UNION ALL

    SELECT 200,'Oct 17 2007 09:45AM' UNION ALL

    SELECT 200,'Oct 17 2007 09:50AM' UNION ALL

    SELECT 200,'Oct 17 2007 11:15AM' UNION ALL

    SELECT 200,'Oct 17 2007 11:30AM' UNION ALL

    SELECT 300,'Oct 17 2007 01:15PM' UNION ALL

    SELECT 300,'Oct 17 2007 01:20PM' UNION ALL

    SELECT 400,'Oct 17 2007 11:20AM' UNION ALL

    SELECT 400,'Oct 17 2007 11:30AM' UNION ALL

    SELECT 600,'Oct 17 2007 08:15AM' UNION ALL

    SELECT 700,'Oct 17 2007 10:05AM' UNION ALL

    SELECT 700,'Oct 17 2007 10:10AM' UNION ALL

    SELECT 800,'Oct 17 2007 09:09AM'

    --===== Set the identity insert back to normal

    SET IDENTITY_INSERT #Arrive OFF

    SET IDENTITY_INSERT #Exit OFF

    Could you please tell me how to do this?

    This is my expect results:

    PatientID ArriveTime ExitTime ThroughputTime (HH:mm)

    ----------- ----------------------- ----------------------- -----------------------

    100 2007-10-17 08:00:00.000 2007-10-17 09:00:00.00001:00

    200 2007-10-17 08:15:00.000 2007-10-17 09:45:00.00001:30

    200 2007-10-17 10:30:00.000 2007-10-17 11:15:00.00000:45

    300 2007-10-17 08:15:00.000 2007-10-17 13:15:00.00005:00

    300 2007-10-17 11:30:00.000 2007-10-17 13:15:00.00001:45

    400 2007-10-17 08:10:00.000 2007-10-17 11:20:00.00003:10

    500 2007-10-17 08:00:00.000 ---------- ---

    700 2007-10-17 09:00:00.000 2007-10-17 10:05:00.00001:05

    700 2007-10-17 11:00:00.000 ---------- ---

    800 2007-10-17 09:15:00.000 ---------- ---

    Thanks for your help.

  • First of all, thank you for providing DDL together with obviously carefully designed sample data! Good job!

    Following please find a proposal that will give you -almost- the expected result (Throughput time for first visit of patient 200 differs, but it looks like a typo on your side...).

    ;WITH

    cte AS (

    SELECT

    a.patientid AS patientid,

    a.arrivetime,

    e.exittime,

    CONVERT(CHAR(23),exittime,121) AS d,

    ROW_NUMBER () OVER(PARTITION BY a.patientid,arrivetime ORDER BY exittime) AS row

    FROM #Arrive a

    INNER JOIN #Exit e ON a.patientid = e.patientid

    WHERE arrivetime= e.exittime

    )

    AND cte.arrivetime IS NULL

    )

    SELECT

    patientid,

    arrivetime,

    d exittime,

    CONVERT(CHAR(5),dateadd(mi,datediff(mi,arrivetime,exittime),0),108) AS [ThroughputTime (HH:mm)]

    FROM cte

    WHERE row=1

    UNION ALL

    SELECT

    patientid,

    arrivetime,

    d exittime,

    '---'

    FROM cte2

    WHERE row=1

    ORDER BY patientid, arrivetime

    Edit: I hope you're on SS2K5, since the Row_Number function won't work.... (missed the forum you posted in...)



    Lutz
    A pessimist is an optimist with experience.

    How to get fast answers to your question[/url]
    How to post performance related questions[/url]
    Links for Tally Table [/url] , Cross Tabs [/url] and Dynamic Cross Tabs [/url], Delimited Split Function[/url]

  • Unfortuneatly, we need a solution for SLQ 2000.

    Our DBA is working on getting 2005 on our test server so we can test the existing app, written for 2000, but is still in the works. Too many projects, not enough time or hardware. Until that happens, no ROWNUMBER for us.

    Cathy Greensfelder (co-worker of Dung Ly)

  • This SQL reproduces your expected results on a SQL 2000 server.

    SELECT

    A.PatientId AS PatientID,

    A.ArriveTime AS ArriveTime,

    MIN(E.ExitTime) AS ExitTime,

    CONVERT(varchar(5), MIN(E.ExitTime) - A.ArriveTime, 108) AS ThroughputTime

    FROM #Arrive A

    LEFT OUTER JOIN #Exit E ON (

    A.PatientId = E.PatientId

    AND A.ArriveTime < E.ExitTime

    AND DATEDIFF(day, A.ArriveTime, E.ExitTime) = 0

    )

    GROUP BY A.PatientId, A.ArriveTime

    ORDER BY A.PatientId, A.ArriveTime

    I'm assuming here that the ArriveTime will always be earlier than the ExitTime for a given patient appointment (i.e. no zero-duration appointments), and that a patient appointment always takes place within a single day and doesn't continue into the following day.

    The final part of the JOIN predicate: DATEDIFF(day, A.ArriveTime, E.ExitTime) = 0 can be removed and the SQL query will still produce your expected results with the supplied test data, but I added it to avoid possible spurious results when the ArriveTime and minimum ExitTime greater that this ArriveTime are on different days. This could happen if an #Exit table record of a particular patient appointment is missing, but an #Exit table record of a later appointment for the same patient exists.

    If the #Arrive and #Exit tables are large, you would get a performance improvement, by changing the primary keys to nonclustered indexes and creating clustered indexes on the PatientId and ArriveTime columns in the case of the #Arrive table, and the PatientId and ExitTime columns in the case of the #Exit table.

  • Hi,

    Edit: Please disregard. Andrews solution (see previous post) is much easier and performs a lot better.

    it's a little more complicated in SS2K (at least in terms of readability), but not impossible...

    I hope it'll run on S2K since I don't have any system to test against.

    An index on PatientID and ArriveTime on table #Arrive and on PatientID and ExitTime on table #Exit should help performance.

    Another option would be to insert the two subselects into a temp table to avoid the UNION operation.

    If this query is performance critical you should also think about a different option to display nonexisting ExitTimes and Throughput since both require a reformatting.

    -- select all visits with valid exit time

    SELECT

    a.patientid AS patientid,

    a.arrivetime,

    MIN(CONVERT(CHAR(23),exittime,121)) AS ExitTime,

    MIN(CONVERT(CHAR(5),dateadd(mi,datediff(mi,arrivetime,exittime),0),108)) AS [ThroughputTime (HH:mm)]

    FROM #Arrive a

    INNER JOIN #Exit e ON a.patientid = e.patientid

    WHERE arrivetime<EXITTIME

    GROUP BY a.patientid ,a.arrivetime

    UNION ALL

    -- select all visits with invalid or no exit time and no arrival time in previous select

    SELECT

    a.patientid AS patientid,

    a.arrivetime,

    '---' AS ExitTime,

    '---'

    FROM #Arrive a

    LEFT OUTER JOIN #Exit e ON a.patientid = e.patientid

    LEFT OUTER JOIN

    (SELECT

    a.patientid AS patientid,

    a.arrivetime

    FROM #Arrive a

    INNER JOIN #Exit e ON a.patientid = e.patientid

    WHERE arrivetime= e.exittime

    )

    AND cte.arrivetime IS NULL

    GROUP BY a.patientid, a.arrivetime

    ORDER BY patientid, arrivetime

    -- result set as requested



    Lutz
    A pessimist is an optimist with experience.

    How to get fast answers to your question[/url]
    How to post performance related questions[/url]
    Links for Tally Table [/url] , Cross Tabs [/url] and Dynamic Cross Tabs [/url], Delimited Split Function[/url]

  • Actually, we CAN have no exit time for the patient and we CAN have the exit time before the arrive time.

    The arrive time is the time the patient checks in with the station desk clerk and the clerk marks him/her as "SHOW" for the appointment. The exit time is when the patient comes back and books his/her follow up appointment. Since not every patient books a follow up appointment, we have a fair number of appointments every day with no exit time. We will just report them as unknown. And it is possible (but not likely) to generate an exit time before the arrive time if the patient decides to book an appointment with a clinic earlier in the day, BEFORE checking in for today's appointment. Unorthodox, but possible.

    We know it's inaccurate but it's what we've got. All the clinics would have to change their process and add a step to get good exit times and it would increase work load for someone. Someone higher up will have to decides it's worthwhile first. So we need a report! 🙂

  • Andrew -

    I knew there was a simple solution but neither one of us could quite see it.

    When Ly gets in and gives it a try with the full data, he'll let you know how it worked out. (I get in a couple hours before he does.)

    Thanks, everyone!

  • It works great. Again thank you for your helps.

Viewing 8 posts - 1 through 8 (of 8 total)

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