2016-07-01 9 views
0

最小化SQLは、私が持っている患者をリストするためのPHPコードを作成した

1-メール 2ゼロ将来の治療 〜3以上で1回の仕上がっ治療 4 - 最新完成治療日がある 問い合わせます今日から3週間前に等しい

問題は、私は50K以上の患者があり、各患者について、上記の条件に多くの時間をかけて質問しています。

3つ以上のクエリを持つすべての患者のクエリではなく、SQLクエリを1つにマージする方法はありますか?

コードは以下の通りです:

$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週間前に 'plan_tdate'を持つ' treatment_type = 1'を想像することができます。現時点では、あなたの質問はそれを無視し、それらを「未来」と数えて、そのような患者をリストから除外します。その意図的(意味的に矛盾している)か、そのような行がdbになるのを防ぐ隠れた制約があるかどうかは分かりません。 – shudder

答えて

1

あなたは、dg_patient_treatment_financeにJOINをLEFT GROUP BYを使用すると、CASE文と組み合わせてSUMを使用することを試みることができます。
同時に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の計算は、計算された合計からコンテンツを取得することで簡略化できます。

関連する問題