2010-04-17 59 views
0

任何人都可以請我發現我的錯誤,這應該是一個SQL合法查詢不應該嗎? ON子句這個SQL怎麼會出錯?我沒有看到什麼?

未知列u.usr_auto_key是數據庫模式:

User: (usr_auto_key, name, etc...) 
Setting: (set_auto_key, name etc..) 
User_Setting: (usr_auto_key, set_auto_key, value) 

這是查詢...

 SELECT 
     `u`.`usr_auto_key` AS `u__usr_auto_key`, 
     `s`.`set_auto_key` AS `s__set_auto_key`, 
     `u2`.`usr_auto_key` AS `u2__usr_auto_key`, 
     `u2`.`set_auto_key` AS `u2__set_auto_key`, 
     `u2`.`value` AS `u2__value` 
     FROM `User` `u`, `Setting` `s` 
     LEFT JOIN `User_Setting` `u2` ON `u`.`usr_auto_key` = `u2`.`usr_auto_key` 
     WHERE (`s`.`sct_auto_key` = 1 AND `u`.`usr_auto_key` = 1 AND admin_property is null) 
+0

您是否檢查過表中沒有拼寫錯誤而不是查詢?發生在我身上不止一次。該查詢是正確的,但是當我創建表時,我輸入了錯誤的列名。 – 2010-04-17 23:44:44

+0

不,它是自動生成的。巴勃羅·桑托克魯茲的答案是正確的。但我不明白:)。(順便說一句,巴勃羅包含一個錯字,它應該是用戶,而不是用戶) – Ropstah 2010-04-17 23:47:28

回答

1

嘗試切換UserSettings在FROM子句:

SELECT 
     `u`.`usr_auto_key` AS `u__usr_auto_key`, 
     `s`.`set_auto_key` AS `s__set_auto_key`, 
     `u2`.`usr_auto_key` AS `u2__usr_auto_key`, 
     `u2`.`set_auto_key` AS `u2__set_auto_key`, 
     `u2`.`value` AS `u2__value` 
     FROM `Setting` `s`, `Users` `u` 
     LEFT JOIN `User_Setting` `u2` ON `u`.`usr_auto_key` = `u2`.`usr_auto_key` 
     WHERE (`s`.`sct_auto_key` = 1 AND `u`.`usr_auto_key` = 1 AND admin_property is null) 
+0

哈哈,你介意解釋一下..? – Ropstah 2010-04-17 23:42:19

+0

它工作嗎? 我想如果你這樣做:用戶u,設置的左邊加入WHATEVER,你試圖在設置上執行加入,而不是用戶。 – 2010-04-17 23:48:17

4

不要混合使用SQL-89 「逗號式」 加盟與SQL-92 JOIN語法句法。這兩種連接操作的優先級存在細微的問題。

就你而言,其結果是它在u表別名存在之前評估連接條件LEFT JOIN。這就是爲什麼它不知道什麼是u.usr_auto_key

您可以通過使用JOIN語法正確的這個問題加入:

SELECT 
    `u`.`usr_auto_key` AS `u__usr_auto_key`, 
    `s`.`set_auto_key` AS `s__set_auto_key`, 
    `u2`.`usr_auto_key` AS `u2__usr_auto_key`, 
    `u2`.`set_auto_key` AS `u2__set_auto_key`, 
    `u2`.`value` AS `u2__value` 
FROM `User` `u` JOIN `Setting` `s` 
LEFT JOIN `User_Setting` `u2` ON `u`.`usr_auto_key` = `u2`.`usr_auto_key` 
WHERE (`s`.`sct_auto_key` = 1 AND `u`.`usr_auto_key` = 1 AND admin_property is null) 

我沒有看到您的查詢us之間的連接條件,所以我想你想這是一個笛卡爾產品?


有關兩種語法形式的加入之間的相互作用的詳細信息,請參見加入處理改變在MySQL 5.0.12頁面http://dev.mysql.com/doc/refman/5.0/en/join.html


回覆您的評論:作爲我說過,這與運營商的優先權有關。如果您有FROM A, B JOIN C的SQL查詢,那麼它會在B JOIN C評估之前對A進行評估 - 包括分配表別名。因此,如果B JOIN C的連接條件使用表別名A,則會出現錯誤,因爲該別名尚不存在。

如果你倒着跑B, A JOIN C然後,因爲它計算爲A JOIN C連接條件爲A別名可用,它的工作原理(在這種情況下,至少)。

但是這是一個脆弱的解決方案,因爲您可能還需要一個無法通過重新排序AB來修復的查詢。最好停止使用帶逗號的過時連接語法。然後,任何聯接表達式都可以訪問您的所有表別名,並且您在任何查詢中都不會遇到此問題。

+0

是的,它需要是笛卡爾產品。但是我無法使用交叉連接。你能解釋一下爲什麼'u'別名是在Pablos的答案中創建的,只是因爲它是第二個而不是第一個(如我的原始查詢)? – Ropstah 2010-04-17 23:57:03

+0

感謝您一路闡述'一路'。我真的需要這種方法,因爲我的ORM框架Doctrine沒有正確執行CROSS JOIN查詢...... – Ropstah 2010-04-18 00:09:16

+0

提示:交叉連接等同於沒有條件的內部連接,或者條件始終爲「true」。 – 2010-04-18 00:48:15

相關問題