2008-11-06 46 views
2

我有以下查詢:如何解決這個MySQL查詢如此有效?

UPDATE lessonstatus 
INNER JOIN user ON lessonstatus.user_id = user.user_id 
SET user_id = (SELECT user_id FROM user WHERE username = 'too_many_accounts') 
WHERE last_name = 'stupid' 
AND first_name = 'user' 
AND username != 'too_many_accounts' 
AND lessonstatus.lesson_id NOT IN (SELECT lesson_id FROM lessonstatus WHERE user_id = 1); 

不過,我得到的時候嘗試下面的錯誤來執行它:

Error Code : 1093 
You can't specify target table 'lessonstatus_rtab' for update in FROM clause 

我將如何解決這個查詢,以便它的工作原理?

+0

術語提示:「重構」是在不修改功能的情況下更改代碼設計。修復損壞的代碼不稱爲「重構」。 – 2008-11-06 17:12:07

+0

安德魯,那是真的。定義「修復破碎的代碼」是什麼正確的術語? – 2008-11-06 17:14:12

回答

3

你不能從SELECT從你在同一個查詢中更新的表(即使在子查詢中)。這就是錯誤「無法指定目標表」的意思。

但是你可以在UPDATE聲明加入userlessonstatus多次,並使用聯接條件創造性地挑選出你想要的各行。

用連接模擬NOT IN的方法是做一個LEFT OUTER JOIN。如果該連接的右側不匹配,那麼NOT IN將是真實的。

UPDATE lessonstatus l1 
    INNER JOIN user u1 ON (l1.user_id = u1.user_id) 
    INNER JOIN user u2 ON (u2.username = 'too_many_accounts') 
    LEFT OUTER JOIN lessonstatus l2 
    ON (l1.lesson_id = l2.lesson_id AND l2.user_id = 1) 
SET l1.user_id = u2.user_id 
WHERE u1.last_name = 'stupid' AND u1.first_name = 'user' 
    AND u1.username != 'too_many_accounts' 
    AND l2.lesson_id IS NULL; -- equivalent to "l NOT IN l2" 

注:我已經測試此查詢語法,但與真實的數據。無論如何,它應該讓你開始。

0

有更多的錯誤(「用戶」表和「user_rtab」的別名不匹配,不建議使用非限定字段名),但UPDATE語法本身應該是相似的:

UPDATE lessonstatus 
SET user_id = (SELECT TOP 1 user_id FROM user WHERE username = 'too_many_accounts') 
FROM lessonstatus 
    INNER JOIN user ON lessonstatus.user_id = user_rtab.user_id 
WHERE last_name = 'stupid' 
    AND first_name = 'user' 
    AND username != 'too_many_accounts' 
    AND lessonstatus.lesson_id NOT IN (
     SELECT lesson_id FROM lessonstatus WHERE user_id = 1 
    );