2013-04-16 97 views
1

我有這個查詢,它增加了一個'stats'表的值的負載。當查詢運行時,它會選擇這些值來填充子查詢中的表。我想知道是否可以更有效地做出這種做法,或者如果我正在做一些非常錯誤的事情。我不是那麼熟悉MySQL的所以任何幫助將是巨大的:)MySQL子查詢效率

下面是該查詢:

UPDATE mediastats SET 
    mediastats_members = (SELECT count(*) FROM status WHERE status_media_id = :id), 
    mediastats_avscore = (SELECT AVG(status_rating) FROM status WHERE status_media_id = :id), 
    mediastats_done = (SELECT count(*) FROM status WHERE status_status = 'done' AND status_media_id = :id), 
    mediastats_doing = (SELECT count(*) FROM status WHERE status_status = 'doing' AND status_media_id = :id), 
    mediastats_redoing = (SELECT count(*) FROM status WHERE status_status = 'redoing' AND status_media_id = :id), 
    mediastats_dropped = (SELECT count(*) FROM status WHERE status_status = 'dropped' AND status_media_id = :id), 
    mediastats_wantto = (SELECT count(*) FROM status WHERE status_status = 'wantto' AND status_media_id = :id), 
    mediastats_wont = (SELECT count(*) FROM status WHERE status_status = 'wont' AND status_media_id = :id), 
    mediastats_stalled = (SELECT count(*) FROM status WHERE status_status = 'stalled' AND status_media_id = :id), 
    mediastats_rating_1 = (SELECT count(*) FROM status WHERE status_rating = 1 AND status_media_id = :id), 
    mediastats_rating_2 = (SELECT count(*) FROM status WHERE status_rating = 2 AND status_media_id = :id), 
    mediastats_rating_3 = (SELECT count(*) FROM status WHERE status_rating = 3 AND status_media_id = :id), 
    mediastats_rating_4 = (SELECT count(*) FROM status WHERE status_rating = 4 AND status_media_id = :id), 
    mediastats_rating_5 = (SELECT count(*) FROM status WHERE status_rating = 5 AND status_media_id = :id), 
    mediastats_rating_6 = (SELECT count(*) FROM status WHERE status_rating = 6 AND status_media_id = :id), 
    mediastats_rating_7 = (SELECT count(*) FROM status WHERE status_rating = 7 AND status_media_id = :id), 
    mediastats_rating_8 = (SELECT count(*) FROM status WHERE status_rating = 8 AND status_media_id = :id), 
    mediastats_rating_9 = (SELECT count(*) FROM status WHERE status_rating = 9 AND status_media_id = :id), 
    mediastats_rating_10 = (SELECT count(*) FROM status WHERE status_rating = 10 AND status_media_id = :id) 
    WHERE mediastats_media_id = :id 

的:ID是從PHP加入。

回答

2

這裏是我如何與PDO做它在PHP:

$sql = " 
    SELECT 
    COUNT(*) AS mediastats_members, 
    AVG(status_rating) AS mediastats_avscore, 
    SUM(status_status = 'done') AS mediastats_done, 
    SUM(status_status = 'doing') AS mediastats_doing, 
    SUM(status_status = 'redoing') AS mediastats_redoing, 
    SUM(status_status = 'dropped') AS mediastats_dropped, 
    SUM(status_status = 'wantto') AS mediastats_wantto, 
    SUM(status_status = 'wont') AS mediastats_wont, 
    SUM(status_status = 'stalled') AS mediastats_stalled, 
    SUM(status_rating = 1) AS mediastats_rating_1, 
    SUM(status_rating = 2) AS mediastats_rating_2, 
    SUM(status_rating = 3) AS mediastats_rating_3, 
    SUM(status_rating = 4) AS mediastats_rating_4, 
    SUM(status_rating = 5) AS mediastats_rating_5, 
    SUM(status_rating = 6) AS mediastats_rating_6, 
    SUM(status_rating = 7) AS mediastats_rating_7, 
    SUM(status_rating = 8) AS mediastats_rating_8, 
    SUM(status_rating = 9) AS mediastats_rating_9, 
    SUM(status_rating = 10) AS mediastats_rating_10 
    FROM status 
    WHERE status_media_id = :id"; 
$stmt = $pdo->prepare($sql); 
$stmt->execute(array("id"=>$id)); 
$params = $stmt->fetch(PDO::FETCH_ASSOC); 

這樣你計算出表的一個通所有的集合體,而是採用了獨立的子查詢每個計數。

我正在使用MySQL的技巧 - 布爾表達式的SUM()等於表達式爲真的COUNT()。這是因爲MySQL布爾表達式總是返回0或1,並且0和1的和等於1的COUNT。

然後你可以從上面的查詢作爲參數數組的UPDATE語句中使用結果:

$sql = " 
    UPDATE mediastats SET 
     mediastats_members = :mediastats_members, 
     mediastats_avscore = :mediastats_avscore, 
     mediastats_done = :mediastats_done, 
     mediastats_doing = :mediastats_doing, 
     mediastats_redoing = :mediastats_redoing, 
     mediastats_dropped = :mediastats_dropped, 
     mediastats_wantto = :mediastats_wantto, 
     mediastats_wont = :mediastats_wont, 
     mediastats_stalled = :mediastats_stalled, 
     mediastats_rating_1 = :mediastats_rating_1, 
     mediastats_rating_2 = :mediastats_rating_2, 
     mediastats_rating_3 = :mediastats_rating_3, 
     mediastats_rating_4 = :mediastats_rating_4, 
     mediastats_rating_5 = :mediastats_rating_5, 
     mediastats_rating_6 = :mediastats_rating_6, 
     mediastats_rating_7 = :mediastats_rating_7, 
     mediastats_rating_8 = :mediastats_rating_8, 
     mediastats_rating_9 = :mediastats_rating_9, 
     mediastats_rating_10 = :mediastats_rating_10 
    WHERE mediastats_media_id = :id"; 

$stmt = $pdo->prepare($sql); 
$params["id"] = $id; 
$stmt->execute($params); 

自PHP 5.3.4,PDO接受參數數組鍵沒有前導:。當您在查詢中聲明參數佔位符時,您需要冒號,但您在提供給execute()的值的數組中不需要冒號。

+0

謝謝你真棒:)這種方法比原來的優點是什麼? – Humphrey

+1

其優點是它可以計算表中一次通過的所有計數。 –

1
UPDATE (
     SELECT status_media_id, 
       COUNT(*) AS cnt, AVG(status_rating) AS avg_rating, 
       SUM(status_status = 'done') AS cnt_done, 
       ... 
     FROM status 
     WHERE status_media_id = :id 
     ) s 
JOIN mediastats ms 
ON  ms.mediastats_media_id = s.status_media_id 
SET  ms.mediastats_members = cnt, 
     ms.mediastats_avscore = avg_rating, 
     ms.mediastats_done = cnt_done, 
     ...