2017-08-01 96 views
0

我創建了此MySQL存儲過程作爲我的問題mentioned in this post on SO的解決方案。MySQL存儲過程在不使用遊標的情況下迭代多個值返回錯誤代碼:1172.結果由多個行組成

下面是該過程:

CREATE DEFINER=`root`@`localhost` PROCEDURE `new_procedure`() 
BEGIN 
DECLARE n, i INT DEFAULT 0; 
DECLARE pid VARCHAR(20); 
DROP temporary table if exists tmp; 
CREATE temporary table tmp 
SELECT 
    t1.patient_id 
FROM 
    consultation t1 
LEFT JOIN diagnosis t2 
    ON t1.diagnosis_id = t2.diagnosis_id 
LEFT JOIN visit t3 
    ON t3.visit_id = t1.visit_id 
LEFT JOIN patient t4 
    ON t4.patient_id = t3.patient_id 
LEFT JOIN diabetes_assessment t5 
    ON t5.patient_id = t4.patient_id 
WHERE 
    t2.diagnosis_name LIKE '%Diabetes%' 
    AND t1.clinic_id = '361' 
    AND t3.visit_status="Active" 
GROUP BY t1.patient_id ; 

set i=1; 
SELECT count(*) INTO n FROM tmp; 
SELECT patient_id into pid FROM tmp; 
while i<=n DO 
    set pid = (select patient_id from tmp); 
SELECT 
    t1.patient_id, 
    CONVERT(aes_decrypt(t4.patient_name_en, 'key') USING utf8mb4) as patient_name_en, 

    min(t3.date_of_visit) as date_of_visit, 
    t2.diagnosis_name, 
    max(ifnull(t5.date_of_assessment, 'N/A')) as date_of_assessment, 
    ifnull(t5.assessment_result, 0) as assessment_result 
FROM consultation t1 
LEFT JOIN diagnosis t2 
    ON t1.diagnosis_id = t2.diagnosis_id 
LEFT JOIN visit t3 
    ON t3.visit_id = t1.visit_id 
LEFT JOIN patient t4 
    ON t4.patient_id = t3.patient_id 
LEFT JOIN diabetes_assessment t5 
    ON t5.patient_id = t4.patient_id 
WHERE 
    t2.diagnosis_name LIKE '%Diabetes%' AND 
    t1.patient_id = pid AND 
    t1.clinic_id = '361' AND 
    t3.visit_status="Active" 
GROUP BY 
    t1.patient_id, 
    t2.diagnosis_name, 
    t3.date_of_visit, 
    t4.patient_name_en, 
    t5.date_of_assessment, 
    t5.assessment_result 
ORDER BY t5.date_of_assessment DESC LIMIT 1; 
set i = i + 1; 
END WHILE; 
END 

我會解釋這一點。下面的查詢將通過patient_id得到patient_ids組,所以only full group by問題得到解決:

DROP temporary table if exists tmp; 
CREATE temporary table tmp 
SELECT t1.patient_id 
FROM consultation t1 
LEFT JOIN diagnosis t2 
    ON t1.diagnosis_id = t2.diagnosis_id 
LEFT JOIN visit t3 
    ON t3.visit_id = t1.visit_id 
LEFT JOIN patient t4 
    ON t4.patient_id = t3.patient_id 
LEFT JOIN diabetes_assessment t5 
    ON t5.patient_id = t4.patient_id 
WHERE t2.diagnosis_name LIKE '%Diabetes%' AND t1.clinic_id = '361' 
AND t3.visit_status="Active" 
GROUP BY t1.patient_id ; 

那麼我就指望我有多少行曾在此臨時表:

set i=1; 
SELECT count(*) INTO n FROM tmp; 

結果2個患者ID。

所以我需要通過每個患者ID迭代:

select patient_id into pid FROM tmp; 

此查詢中:

while i<=n DO 
set pid = (select patient_id from tmp); 
SELECT 
    t1.patient_id, 
    CONVERT(aes_decrypt(t4.patient_name_en, 'key') USING utf8mb4) as patient_name_en, 
    min(t3.date_of_visit) as date_of_visit, 
    t2.diagnosis_name, 
    max(ifnull(t5.date_of_assessment, 'N/A')) as date_of_assessment, 
    ifnull(t5.assessment_result, 0) as assessment_result 
FROM consultation t1 
LEFT JOIN diagnosis t2 
    ON t1.diagnosis_id = t2.diagnosis_id 
LEFT JOIN visit t3 
    ON t3.visit_id = t1.visit_id 
LEFT JOIN patient t4 
    ON t4.patient_id = t3.patient_id 
LEFT JOIN diabetes_assessment t5 
    ON t5.patient_id = t4.patient_id 
WHERE 
    t2.diagnosis_name LIKE '%Diabetes%' AND 
    t1.patient_id = pid AND 
    t1.clinic_id = '361' AND 
    t3.visit_status="Active" 
GROUP BY 
    t1.patient_id, 
    t2.diagnosis_name, 
    t3.date_of_visit, 
    t4.patient_name_en, 
    t5.date_of_assessment, 
    t5.assessment_result 
ORDER BY t5.date_of_assessment DESC LIMIT 1; 
set i = i + 1; 
END WHILE; 

我想我的問題是在這兩條線:

select patient_id into pid FROM tmp; 

而且

set pid = (select patient_id from tmp); 

錯誤是:

我不想使用遊標,因爲我們的教授曾經說過遊標是足智多謀且不好的做法。

錯誤代碼:1172結果由多行的

+0

試試限制1'set pid =(從tmp limit 1中選擇patient_id);' –

+0

仍然是同樣的錯誤 – droidnation

+0

試過兩條線? '將patient_id選擇到pid FROM tmp;'和'set pid =(從tmp limit 1中選擇patient_id); ' –

回答

1

如果你得到兩個不同的patiend ID和希望通過兩個迭代,那麼你需要使用CURSOR,如:

DECLARE patient_id_cursor CURSOR FOR SELECT patient_id FROM tmp; 

OPEN patient_id_cursor; 
FETCH cursor_name INTO pid; 
/* 
Logic to process `pid` 
*/ 
CLOSE patient_id_cursor; 
+0

完美的一個.. !! –

+0

但遊標不再使用,是不正確的做法嗎? – droidnation

+0

不,[這裏是](https://dev.mysql.com/doc/refman/5.7/en/cursors.html)遊標上的MySQL文檔。 –