SQL query - Join that returns the first two records of joining table

后端 未结 8 1729
陌清茗
陌清茗 2021-02-02 03:50

I have two tables:

Patient

  • pkPatientId
  • FirstName
  • Surname

PatientStatus

  • pk
相关标签:
8条回答
  • 2021-02-02 04:13

    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!)

    0 讨论(0)
  • 2021-02-02 04:16

    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.

    0 讨论(0)
提交回复
热议问题