2016-07-01 90 views
0

我創建了一個PHP代碼上市誰都有患者最小化SQL查詢

1電子郵件 2零未來治療 3等於或大於1個完成治療 4 - 最新完成的處理日期爲相當於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>'; 

     } 
    } 
+0

實際上,您的條件2,3和4可能意味着*最近的治療是3周前的*。至少從語義的角度來看 - 我不知道你的'treatment_type'是如何處理的。你能直接應用這個邏輯還是不允許它? – shudder

+0

如果treatment_type爲1表示未來的治療,如果爲2則表示治療結束。 – adams

+0

在db(行)的上下文中,「future treatment」不是由將來的日期決定的,而是由指定的類型決定的,所以我可以想象上週或3周前'treatment_type = 1'具有'plan_date'。目前,您的查詢忽略了這一點,並將它們計爲「未來」,從而將此類患者從名單中刪除。不知道它的有意(儘管在語義上矛盾)或有一些隱藏的約束,可以防止在db中有這樣的行。 – shudder

回答

1

你可以嘗試LEFT JOIN上dg_patient_treatment_finance,使用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計算。