I have two tables:
Patient
PatientStatus
EDIT: Both of the following solutions require that PatientStatus.StartDate
is unique within each patient.
The traditional way (SQL Server 2000 compatible):
SELECT
p.pkPatientId,
p.FirstName,
p.Surname,
ps.StatusCode,
ps.StartDate,
ps.EndDate
FROM
Patient p
INNER JOIN PatientStatus ps ON
p.pkPatientId = ps.fkPatientId
AND ps.StartDate IN (
SELECT TOP 2 StartDate
FROM PatientStatus
WHERE fkPatientId = ps.fkPatientId
ORDER BY StartDate /* DESC (to switch between first/last records) */
)
WHERE
EXISTS (
SELECT 1
FROM PatientStatus
WHERE fkPatientId = p.pkPatientId
GROUP BY fkPatientId
HAVING COUNT(*) >= 2
)
ORDER BY
ps.fkPatientId,
ps.StartDate
A more interesting alternative (you'd have to try how well it performs in comparison):
SELECT
p.pkPatientId,
p.FirstName,
p.Surname,
ps.StatusCode,
ps.StartDate,
ps.EndDate
FROM
Patient p
INNER JOIN PatientStatus ps ON p.pkPatientId = ps.fkPatientId
WHERE
/* the "2" is the maximum number of rows returned */
2 > (
SELECT
COUNT(*)
FROM
Patient p_i
INNER JOIN PatientStatus ps_i ON p_i.pkPatientId = ps_i.fkPatientId
WHERE
ps_i.fkPatientId = ps.fkPatientId
AND ps_i.StartDate < ps.StartDate
/* switch between "<" and ">" to get the first/last rows */
)
AND EXISTS (
SELECT 1
FROM PatientStatus
WHERE fkPatientId = p.pkPatientId
GROUP BY fkPatientId
HAVING COUNT(*) >= 2
)
ORDER BY
ps.fkPatientId,
ps.StartDate
Side note: For MySQL the latter query might be the only alternative - until LIMIT is supported in sub-queries.
EDIT: I added a condition that excludes patients with only one PatientStatus
record. (Thanks for the tip, Ryan!)
Here is how I would approach this:
-- Patients with at least 2 status records
with PatientsWithEnoughRecords as (
select fkPatientId
from PatientStatus as ps
group by
fkPatientId
having
count(*) >= 2
)
select top 2 *
from PatientsWithEnoughRecords as er
left join PatientStatus as ps on
er.fkPatientId = ps.fkPatientId
order by StartDate asc
I am not sure what determines the "first" two status records in your case, so I assumed you want the earliest two StartDate
**s. Modify the last **order by
clause to get the records that you are interested in.
Edit: SQL Server 2000 doesn't support CTEs, so this solution will indeed only work directly on 2005 and later.