Click here to Skip to main content
15,890,438 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am trying to show the first and last appointment of a specific patient at the same time. So the output will look something like this below…the “|” symbol below represents the separation of columns.

PatientID | First Appt Date| First Appt Date Status | First Appt Visit Type| Last Appt Date| Last Appt Date Status| Last Appt Visit Type

So for example, if I want to query the first and last appointment for PatientID 500, how would I do that?

The table the information is being pulled from looks like this below:

PatientID| APPTDATE| STATUS| VISITTYPE| VISITTIME|LOCATION

What I have tried:

Select PatientID, ApptDate, STATUS, VisitType From ModifiedApptTable
Where PatientID = 500
Posted
Updated 10-Apr-20 22:13pm
v2

I think, you are able to achieve that using JOIN, MIN and MAX this way:
SQL
--based on example provided in solution #1
SELECT t1.*
FROM @Temp t1 INNER JOIN 
(
	SELECT PatientID, MIN(ApptDate) MinApptDate, MAX(ApptDate) MaxApptDate
	FROM @Temp
	Where PatientID = 500
	GROUP BY PatientID
) t2
 ON t1.ApptDate = t2.MinApptDate OR t1.ApptDate = t2.MaxApptDate


You'll get 2 rows as a result ;)
 
Share this answer
 
Comments
MadMyche 4-Apr-20 7:51am    
I think I'm going to do this as a SProc and get it over with lol
Based on your original content I have created the following Table and populated it. Please note that the variances in column names: this is because both Status and Location are special/reserved words in SQL Server and me editor (SSMS) highlighted them
SQL
CREATE TABLE TestData (
  PatientID   int,
  ApptDate    date,
  ApptStatus  varchar(32),
  VisitType   varchar(32),
  VisitTime   time,
  Facility    varchar(32)
)
GO
INSERT TestData VALUES
  (101, '01/01/2001', 'Complete', 'Flu complaint', '08:00', 'TeleMed')
, (101, '01/11/2001', 'Complete', 'Blood draw', '11:30', 'Outpatient Lab')
, (500, '05/01/2005', 'Complete', 'Broken Leg', '08:00', 'ER')
, (500, '06/01/2005', 'Complete', 'XRays', '17:00', 'Radiology')
, (600, '06/06/2005', 'Complete', 'Medical Complaint', '09:00', 'ER')
GO
The way I am going to write this is going to involve the use of 3 variables within the SQL environment. The first one (@PatientID) will be used to determine what patient you want the data on; and the other two (@FirstDate, @LastDate) will be used to determine the first and last appointment dates.
SQL
DECLARE @PatientID INT = 500
DECLARE @FirstDate DATE
DECLARE @LastDate  DATE

SELECT @FirstDate = Min(ApptDate), @LastDate = Max(ApptDate)
FROM   TestData
WHERE  (PatientID = @PatientID)
Now that we have these values all determined, we do not need to use sub-queries and it just becomes a matter of using these variables within a JOIN statement to flatten out the results into one row
SQL
SELECT f.PatientID
,      FirstApptDate   = f.ApptDate
,      FirstApptStatus = f.ApptStatus
,      FirstApptType   = f.VisitType
,      LastApptDate    = l.ApptDate
,      LastApptStatus  = l.ApptStatus
,      LastApptType    = l.VisitType
FROM       TestData f
INNER JOIN TestData l   ON f.PatientID = l.PatientID
                       AND f.ApptDate  = @FirstDate
                       AND l.ApptDate  = @LastDate
WHERE  (f.PatientID = @PatientID)
 
Share this answer
 
Comments
Maciej Los 4-Apr-20 9:33am    
More elegant and efficient solution deserves for 5!
MadMyche 4-Apr-20 12:44pm    
Thank you...
The solution you seek is going to involve a little more than a simple 1 line SQL statement, and the best way would utilize the Min and Max Aggregate functions
MIN (Transact-SQL) - SQL Server | Microsoft Docs[^]
MAX (Transact-SQL) - SQL Server | Microsoft Docs[^]

Once you work out how to get them values...
1. You get to use them within a subquery to get just the first appt info for that particular patient
2. You get to write another query/subquery combination to get the last appt info

OK, so you now have 2 queries (w/ subqueries) to get the first and last appt information.
Now you can JOIN them together to get the information all in one row.

This sample just has PatientID and the dates in it... It is not something I would use in production but it is fully functional. What it does show is how all of this can be done
SQL
DECLARE @Temp Table ( PatientID int, ApptDate date )

INSERT @Temp VALUES
    (101, '01/01/2001'), (101, '01/11/2001'), (500, '05/01/2005'), (500, '06/01/2005'), (600, '06/06/2005')

SELECT f.PatientID
,      FirstApptDate       = f.ApptDate
,      LastApptDate        = l.ApptDate

FROM (
     SELECT PatientID, ApptDate
     FROM   @Temp
     WHERE  ApptDate = (
          SELECT Min(ApptDate)
		FROM   @Temp
		WHERE  PatientID = 500 )         ) as F
INNER JOIN  (
     SELECT PatientID, ApptDate
     FROM   @Temp
     WHERE  ApptDate = (
	     SELECT FirstDate = Max(ApptDate)
          FROM   @Temp
          WHERE PatientID = 500)           ) as L ON  f.PatientID = l.PatientID
WHERE f.PatientID = 500
For a production script... this would be replaced with a Stored Procedure which would use a few more variables and not rely on all the sub-queries
 
Share this answer
 
Comments
Maciej Los 4-Apr-20 6:18am    
Well... i'd avoid of using several subqueries due to the performance of query. Please, see my answer.
MadMyche 4-Apr-20 7:49am    
Never said it was pretty.... but all the concepts are there... and I said I would not use it in production.
select * from (select top 1 PatientID, APPTDATE, STATUS, VISITTYPE from ModifiedApptTable Where PatientID = 500 order by APPTDATE) a union select * from (select top 1 PatientID, APPTDATE, STATUS, VISITTYPE from ModifiedApptTableWhere PatientID = 500 order by APPTDATE desc) b
 
Share this answer
 
DROP TABLE #TMP 
SELECT [PatientID],
MAX(APPTDATE) M,MIN(APPTDATE) AS MN INTO #TMP
FROM TESTDATA S 
GROUP BY [PatientID];

WITH CTE
AS
(
SELECT T.[PatientID], [ApptDate], [ApptStatus], [VisitType], [VisitTime], [Facility],'MAXdATE'  AS RANGE
FROM TESTDATA T WHERE EXISTS (
SELECT  * FROM #TMP P WHERE P.[PatientID]=T.[PatientID] AND P.M=T.[ApptDate])
UNION ALL
SELECT T.[PatientID], [ApptDate], [ApptStatus], [VisitType], [VisitTime], [Facility],'MINDATE' AS RANGE
FROM TESTDATA T WHERE EXISTS (
SELECT  * FROM #TMP P WHERE P.[PatientID]=T.[PatientID] AND P.MN=T.[ApptDate])
)

SELECT * FROM CTE  WHERE [PatientID]=101
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900