2012-03-17 34 views
1

我試圖一次從多個表中獲取數據。在我的舊系統中,我將進行查詢,獲取我需要的數據,然後將其用於下一個查詢。我想避免多次查詢,所以我結合他們加入:爲什麼這個JOIN不合法?

SELECT `to`.`id` , `to`.`group`, `to`.`email`, `pTo`.`min_offer`, COUNT(`offerRes`.`id`), `settingsRes`.`email` 
           FROM `members` AS `to` 

           LEFT JOIN (
            SELECT `id` , `min_offer` 
            FROM `profile` 
           ) pTo ON pTo.id = to.id 

           LEFT JOIN (
            SELECT `id`, `from`,`to` 
            FROM `offers` 
           ) offerRes ON offerRes.from = ? && offerRes.to = to.id 

           LEFT JOIN (
            SELECT `id`, `email` 
            FROM `user_settings` 
           ) settingsRes ON settingsRes.id = to.id 

           WHERE to.id = ? LIMIT 1 

我使用在(to.id)獲得來自profiles表結果和報價表和用戶設置表通過ID 。這些表都有一個PRIMARY ID,所有東西都映射到這個ID上。我的PHP用戶準備了語句,但我替換了?在PHPMyAdmin中有很大的價值。我解釋的是如下:

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 PRIMARY   to  const PRIMARY  PRIMARY 4   const  1 
1 PRIMARY  <derived2> ALL  NULL   NULL NULL NULL  45 
1 PRIMARY  <derived3> ALL  NULL   NULL NULL NULL  1 
1 PRIMARY  <derived4> ALL  NULL   NULL NULL NULL  15 
4 DERIVED  user_settingsALL NULL   NULL NULL NULL  15 
3 DERIVED  offers  system NULL   NULL NULL NULL  1 
2 DERIVED  profile  ALL  NULL   NULL NULL NULL  45 

爲什麼MySQL的經歷全部45列的配置文件字段時,它可以做一個簡單的查找我的查詢基於該主鍵id?任何方式使這更有效率?我要的是下面的表格:

id (from members) - this is optional as this is what is obtained from the user and passed in to SELECT against 
group (from members) - corresponding to the id that is passed in 
email (from members) - corresponding to the id that is passed in 
min_offer (from profile) - also corresponding to the id that is passed in 
NUM_ROWS(from offers) - number of rows corresponding to the id taht is passed in and another number that is also passed in. The offers table has a PRIMARY id but it is a different ID than what is passed in. 
email (from user_settings) - corresponding to the id that is passed in 
+1

非INNER聯接越多,查詢效率越低。 – 2012-03-17 03:13:25

+0

據我所知,與內部聯接如果任何這些子查詢返回沒有行整個事情返回NULL。這是不可取的。我仍然不明白爲什麼它在進行左連接時搜索所有45條記錄idCol = someOtherIdCol。 ID是主鍵。除非我正在閱讀EXPLAIN錯誤,否則不應該搜索45行? – user974896 2012-03-17 03:18:06

+0

左連接應檢查45行。表中所有行的成員都會在結果中,找不到對應於另一個表的行會有空字段 – Jhonathan 2012-03-17 03:23:07

回答

3

爲什麼MySQL的經歷全部45列的配置文件字段時,我的查詢基於該主鍵ID就可以做一個簡單的查找?

因爲要加入到結果子查詢,其中包括從表中每一條記錄:

LEFT JOIN (
    SELECT `id` , `min_offer` 
    FROM `profile` 
) pTo ON pTo.id = to.id 

-- etc. 

相反,加入到直接表:

LEFT JOIN `profile` AS pTo ON pTo.id = to.id 

LEFT JOIN `offers` AS offerRes ON offerRes.from = ? && offerRes.to = to.id 

LEFT JOIN `user_settings` AS settingsRes ON settingsRes.id = to.id 
+0

完美。非常高效,並按照預期運行。我不知道如何使用JOIN。我認爲你需要在JOINed查詢中指定你想要的字段,以便稍後可以「訪問」這些變量(即現在我可以在另一個查詢中使用pTo'.min_offer)。現在,我看到你可以這樣做,爲什麼在世界上任何人都會像我以前那樣使用子查詢?這將很多查詢合併爲1並仍然保持效率。 – user974896 2012-03-17 04:04:11