2011-03-24 110 views
1

我敢肯定,我需要做對我的表左外連接,但我不知道這是100%真實或語法來寫它們的MySQL。與左外連接的問題

我有這個疑問寫:

select m.mechanic_id, 
    m.mechanic_name, 
    m.city, 
    m.state, 
    count(mr.mechanic_id) as num_ratings, 
    round(avg(mr.quality_id),2) quality_rating 
    round(avg(mr.friendly_id),2) friendly_rating, 
    round(avg(mr.professional_id),2) professional_rating 
from mechanic m, mechanic_rating mr, rating r 
where m.mechanic_id in (1) 
and m.mechanic_id = mr.mechanic_id 
and mr.quality_id = r.rating_id(+) <-- these cause issues 
and mr.friendly_id = r.rating_id(+) <-- these cause issues 
and mr.professional_id = r.rating_id(+) <-- these cause issues 
group by mechanic_id 

的(+)是做在Oracle外連接,我不知道如何手動編寫出在此查詢的外部連接的一種方式。我甚至不確定我是否將它們放在正確的列上。

我的表結構看起來像這樣

機械錶

|mechanic_id|mechanic_name|city|state|zip| 
|PK   | 

評分表

|rating_id|rating | 
|1  |terrible| 
|2  |bad  | 
etc. 

Mechanic_Rating表

|mechanic_rating_id|mechanic_id|quality_id|friendly_id|professional_id| 
|unique auto inc |FK   | 

的quality_id,友好_id和professional_id都應該是評級表中rating_id的外鍵。

如果我從我的查詢起飛(+),我得到結果爲零,所以我在想,問題是,我需要做的左外連接。讓我知道你是否需要更多信息。

回答

2

您需要學習和使用ANSI-92標準語法來完成Join謂詞。使用ANSI-92,您的查詢將被寫爲

select m.mechanic_id, m.mechanic_name, m.city, 
    m.state, count(mr.mechanic_id) num_ratings, 
    round(avg(mr.quality_id),2) quality_rating 
    round(avg(mr.friendly_id),2) friendly_rating, 
    round(avg(mr.professional_id),2) professional_rating 
from mechanic m 
    Left Join mechanic_rating mr 
     On mr.mechanic_id = m.mechanic_id 
    Left Join rating r 
     On r.rating_id = mr.quality_id 
      And r.rating_id = mr.friendly_id 
      And r.rating_id = mr.friendly_id 
where m.mechanic_id in (1) 
group by mechanic_id 

注意:(1)是指什麼?你們是不是要限制這
其中m.mechanic_id = 1?

+0

我在我的應用程序中使用了一個包含一個或多個ID的變量。我只用「1」來測試我的查詢。 – Catfish 2011-03-24 02:44:11

+0

我假設這個變量是一個表變量?否則,你不需要做一個Group By ... – 2011-03-24 14:36:37

1

這應該與您解決問題(+);使用LEFT OUTER JOIN意味着來自左表都將被列入即使沒有右表中的一個元素。同樣,右側的所有列(如果沒有匹配)都將爲NULL。

select m.mechanic_id, 
    m.mechanic_name, 
    m.city, 
    m.state, 
    count(mr.mechanic_id) as num_ratings, 
    round(avg(mr.quality_id),2) quality_rating 
    round(avg(mr.friendly_id),2) friendly_rating, 
    round(avg(mr.professional_id),2) professional_rating 
FROM mechanic m LEFT OUTER JOIN mechanic_rating mr ON(m.mechanic_id = mr.mechanic_id) 
LEFT OUTER JOIN rating r ON(mr.quality_id = r.rating_id AND 
mr.friendly_id = r.rating_id AND mr.professional_id = r.rating_id) 
WHERE m.mechanic_id in (1) GROUP BY mechanic_id 
+0

我想你混淆'和'LEFT LEFT OUTER JOIN' JOI N'。 – Yahel 2011-03-24 02:33:21

+0

有什麼區別? – Catfish 2011-03-24 02:33:50

+0

您的兩個查詢的結果都是一樣的。是不是外在暗示? – Catfish 2011-03-24 02:34:36

1

你的評級是獨立的,正交的,對不對?你需要在不同的別名使用相同的等級表:

from mechanic m 
    Left Join mechanic_rating mr 
     On mr.mechanic_id = m.mechanic_id 
    Left Join rating r_quality 
     On r_quality.rating_id = mr.quality_id 
    Left Join rating r_friendly 
     On r_friendly.rating_id = mr.friendly_id 
    Left Join rating r_professional 
     On r_professional.rating_id = mr.professional_id 

結合他們都爲你所做的是要簡單地過濾掉其中的獨立評級不都是相同的所有行,這可能是另一回事影響你看到的結果。

雖然它的外鍵的同桌,每個按鍵都是獨立的,所以你需要「角色」爲錶行事。

然而,因爲你不使用任何等級列您的選擇列表,實際上你可以把它們完全出來:

select m.mechanic_id, 
    m.mechanic_name, 
    m.city, 
    m.state, 
    count(mr.mechanic_id) as num_ratings, 
    round(avg(mr.quality_id),2) quality_rating 
    round(avg(mr.friendly_id),2) friendly_rating, 
    round(avg(mr.professional_id),2) professional_rating 
from mechanic m, mechanic_rating mr 
where m.mechanic_id in (1) 
and m.mechanic_id = mr.mechanic_id 
group by mechanic_id 

請注意,您還可以修復你的舊樣式聯接:

from mechanic m, mechanic_rating mr, rating r_quality, rating r_friendly, rating r_professional 
where m.mechanic_id in (1) 
and m.mechanic_id = mr.mechanic_id 
and mr.quality_id = r_quality.rating_id(+) 
and mr.friendly_id = r_friendly.rating_id(+) 
and mr.professional_id = r_professional.rating_id(+) 
group by mechanic_id