最小化SQL查询

时间:2016-07-01 11:08:18

标签: php sql join

我已经创建了一个用于列出

患者的PHP代码

1的电子邮件 2零未来治疗 3等于或超过1完成治疗 4-latest完成治疗日期从今天开始等于3周前

问题是,我有超过50K的患者,每个患者都要花很多时间查询上述情况。

有没有办法将sql查询合并为一个,而不是每个有3个或更多查询的患者合并大约200k个查询?

代码如下:

$today = date('Y-m-d');
$three_weeks_ago = date('Y-m-d', strtotime($today.'-3 weeks'));
$patients = $db->query("
SELECT 
    dg_patients_patients.id,
    dg_patients_patients.first_name,
    dg_patients_patients.last_name,
    dg_patients_patients.email,
    dg_clinics.clinic_name,
    dg_clinics.clinic_address,
    dg_clinics.clinic_phone 
FROM dg_patients_patients 
    LEFT JOIN dg_clinics ON dg_patients_patients.clinic_id = dg_clinics.id 
WHERE dg_patients_patients.email <> '' ORDER BY dg_patients_patients.first_name ASC ");

$now = date('Y-m-d H:i:s');

foreach ($patients as $row){

    $patientID = $row['id'];

    //Get Patient Future Treatments
    $check_future_treatments = $db->column("SELECT id FROM dg_patient_treatment_finance WHERE treatment_type = :a1 AND patient_id = :a2 ",array("a1"=>"1","a2"=>"$patientID"));
    $future_treatments = count($check_future_treatments);

    //Get Patient Finished Treatments
    $check_finished_treatments = $db->column("SELECT id FROM dg_patient_treatment_finance WHERE treatment_type = :a1 AND patient_id = :a2 ",array("a1"=>"2","a2"=>"$patientID"));
    $finished_treatments = count($check_finished_treatments);


    if($future_treatments == 0 && $finished_treatments > 0 ) {

        $latest_finished_treatment_date = $db->single("SELECT plan_date FROM dg_patient_treatment_finance WHERE patient_id = :pid ORDER BY plan_date DESC LIMIT 1 ", array("pid"=>"$patientID"));

        if($latest_finished_treatment_date == $three_weeks_ago){

            echo $patientID.'- '.$row['first_name'].' '.$row['last_name'].' - '.$row['email'].'<br>';

        }
    }

1 个答案:

答案 0 :(得分:1)

您可以尝试在dg_patient_treatment_finance上进行LEFT JOIN,使用GROUP BY并将SUM与CASE语句结合使用。
并同时计算MAX plan_date。

SELECT 
    p.id, p.first_name, p.last_name, p.email,
    c.clinic_name, c.clinic_address, c.clinic_phone,
    SUM(case when tf.treatment_type = 1 then 1 else 0 end) as total_treatment_type_1,
    SUM(case when tf.treatment_type = 2 then 1 else 0 end) as total_treatment_type_2,
    MAX(tf.plan_date) as max_plan_date
FROM dg_patients_patients p
LEFT JOIN dg_clinics c ON (p.clinic_id = c.id)
LEFT JOIN dg_patient_treatment_finance tf ON (p.id = tf.patient_id and tf.treatment_type IN (1,2))
WHERE p.email <> '' 
GROUP BY 
    p.id, p.first_name, p.last_name, p.email,
    c.clinic_name, c.clinic_address, c.clinic_phone
ORDER BY p.first_name, p.last_name

然后,您还可以通过从计算的总和中获取内容来简化$ future_treatments和$ finished_treatments的计算。