首页 > 解决方案 > MySQL:用于选择唯一患者的查询

问题描述

我遇到了一个不返回唯一记录的查询。

我有以下表格:

clinics (id => PK)
patients (id => PK, clinic_id => FK)
patient_visits(id => PK, patient_id => FK, clinic_id => FK)

患者在诊所登记。患者可以多次访问任何诊所。我想要的是返回所有在诊所就诊的独特患者。

我尝试了以下查询,该查询未返回诊所的唯一记录

SELECT v.id
     , v.patient_id
     , v.clinic_id
     , c.name clinic_name
     , p.name
     , p.mobile
     , p.email
     , p.gender
     , p.created_at
     , last_visit_date
     , visit_count 
  FROM 
     ( SELECT DISTINCT patient_id
                     , clinic_id 
                  FROM patient_visits
     ) pat
  JOIN patient_visits v
    ON pat.patient_id = v.patient_id 
  JOIN clinics c
    ON c.id = v.clinic_id 
  JOIN patients p
    ON p.id = v.clinic_id 
  JOIN 
     ( SELECT patient_id
            , MAX(patient_visits.created_at) last_visit_date
            , COUNT(patient_visits.created_at) visit_count 
         FROM patient_visits 
        GROUP 
           BY patient_id
     ) visits_aggregate 
    ON visits_aggregate.patient_id = p.id 
 WHERE v.clinic_id = ? 
 ORDER 
    BY visit_date

我理解的一个问题是,如果我加入了 patient_visits,它将选择匹配的重复的 patient_id、clinic_id 组合。

标签: mysql

解决方案


您应该避免加入所有行,patients_visits因为它会导致臭名昭著的组合爆炸导致重复行。你需要一个聚合。

但是,您的示例显示patient_visits.id. 如果您不希望每次访问的结果集中出现重复,则不能显示该列;每次访问都有不同的价值。

您需要来自 patient_visits 表的聚合,如下所示:

               SELECT patient_id, clinic_id, 
                      MAX(created_at) last_visit_date,
                      COUNT(*) visit_count
                 FROM patient_visits
                GROUP BY patient_id, clinic_id

该查询包含每个患者和诊所组合的一行,因此您可以将其加入其他表而不会生成重复行。在您这样做之前,请单独运行它以说服自己它可以正常工作。

然后......像这样在您的查询中使用它

select patients.id patient_id, clinics.id clinic_id, 
       clinics.name as clinic_name, 
       patients.name, patients.mobile, patients.email, patients.gender, 
       patients.created_at, 
       pv.last_visit_date, pv.visit_count
  from patients
  join (       SELECT patient_id, clinic_id, 
                      MAX(created_at) last_visit_date,
                      COUNT(*) visit_count
                 FROM patient_visits
                GROUP BY patient_id, clinic_id
       ) pv ON patients.id = pv.patient_id
  join clinics ON pv.clinic_id = clinics.id
 order by pv.last_visit_date

看看这是如何工作的?您不想要所有访问,只需要它们的总和,给出最近一次的日期和计数。


推荐阅读