左外连接的问题

时间:2011-03-24 02:21:06

标签: mysql database join

我很确定我需要在我的表上做左外连接,但我不确定这是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,friendly_id和professional_id都应该是评级表中rating_id的外键。

如果我从我的查询中取消(+),我得到零结果,所以我认为问题是我需要做左外连接。如果您需要更多信息,请告诉我。

3 个答案:

答案 0 :(得分:2)

您需要学习并使用ANSI-92标准语法来执行连接谓词。使用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?

答案 1 :(得分: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

答案 2 :(得分: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