tags:

views:

123

answers:

4
Patient 
-------
PatientID

Visit
-----
VisitID
PatientID
HeartRate
VisitDate

How do I select all of the patients who have a visit, the date of their first visit, and their heart rate at that first visit?

A: 
SELECT TOP(1) PatientID, VisitDate, HeartRate FROM Visit ORDER BY VisitDate ASC

Patient has only PatientID? Not a name or something like that?

Gonzalo Quero
I only posted the relevant columns from patient. Anyway I need the first visit :<
Shawn Simon
Then it would be something like this.
Gonzalo Quero
Doesn't he want all the patients with visits?
David B
You're right, this is a wrong answer. I'm sorry
Gonzalo Quero
+1  A: 

Is this what you want? Of course the join isn't really necessary here since there are no extra fields in Patient. But I guess IRL there are.

select PatientId, HeartRate, VisitDate from Patient p
left join Visit v on p.PatientID = v.PatientId
Gerrie Schenck
sorry ened the first visit. and this would be an inner join ;p
Shawn Simon
The query is the same, but add a 'SORT BY VisitDate DESC GROUP BY PatientId' to it.
workmad3
+7  A: 
SELECT
  p.PatientID,
  v.VisitID,
  v.HeartRate,
  v.VisitDate
FROM
  Patient p
  INNER JOIN Visit v ON p.PatientID = v.PatientID
WHERE
  v.VisitDate = (
    SELECT MIN(VisitDate) 
    FROM Visit 
    WHERE PatientId = p.PatientId
  )


EDIT: Alternative version. Same thing. (less obvious, therefore less desirable IMHO)

SELECT
  p.PatientID,
  v.VisitID,
  v.HeartRate,
  v.VisitDate
FROM
  Patient p
  INNER JOIN Visit v ON p.PatientID = v.PatientID
  INNER JOIN (
    SELECT PatientID, MIN(VisitDate) VisitDate 
    FROM Visit 
    GROUP BY PatientID
  ) f ON f.PatientID = p.PatientID AND f.VisitDate = v.VisitDate
Tomalak
hrmm this is close to what i had, i was hoping there was a better way though. thanks so much
Shawn Simon
I don't think there is a "better" way to do it. However you define that. If you mean "without using a sub-query"... You could add an INNER JOIN against "(SELECT PatientID, MIN(VisitDate) FROM Visit GROUP BY PatientID)". But that's just the sub-query in disguise.
Tomalak
more so that youre joining on the patientID / visit date combo. but i think its the only way
Shawn Simon
Yes, you could move the WHERE condition of my version 1 query to the join condition (simply replace "WHERE" by "AND"). If it makes you happy. :-) SQL Server will produce the same query plan.
Tomalak
+1  A: 

The final query

declare @practiceID int 
select 
 isnull(sum(isResponder),0) as [Responders],
 isnull(count(*) - sum(isResponder),0) as [NonResponders]
from ( 
 select 
  v.patientID
  ,firstVisit.hbLevel as startHb
  ,maxHbVisit.hblevel as maxHb
  , case when (maxHbVisit.hblevel - firstVisit.hbLevel >= 1) then 1 else 0 end as isResponder
 from patient p 
  inner join visit v on v.patientid = v.patientid 
  inner join practice on practice.practiceid = p.practiceid
  inner join (
   SELECT
     p.PatientID
     ,v.VisitID
     ,v.hblevel 
     ,v.VisitDate 
   FROM Patient p
     INNER JOIN Visit v ON p.PatientID = v.PatientID
   WHERE
    v.VisitDate = (
     SELECT MIN(VisitDate) 
     FROM Visit 
     WHERE PatientId = p.PatientId
     )
  ) firstVisit on firstVisit.patientID = v.patientID
  inner join (
   select 
    p.patientID
    ,max(v.hbLevel) as hblevel
   from Patient p
     INNER JOIN Visit v ON p.PatientID = v.PatientID
   group by
    p.patientID
  ) MaxHbVisit on maxHbVisit.patientid = v.patientId
 where
  p.practiceID = isnull(@practiceID, p.practiceID)
 group by
  v.patientID
  ,firstVisit.hbLevel
  ,maxHbVisit.hblevel
 having
  datediff(
   d,
   dateadd(
    day
    ,-DatePart(
     dw
     ,min(v.visitDate)
    ) + 1
    ,min(v.visitDate)
   )
   , max(v.visitDate)
  ) >= (7 * 8)
) responders
Shawn Simon