MySQL通过一个共同条件和一个交叉表条件加入两个表

MySQL通过一个共同条件和一个交叉表条件加入两个表

问题描述:

我想从网站5中选择所有图库并加入其类别以显示类别的名称。我的问题是:以下三种选择这些数据的方法是相同的,还是就速度而言有所不同?MySQL通过一个共同条件和一个交叉表条件加入两个表

1)

SELECT * 
FROM `gallery` 
    JOIN `category` 
     ON 
      `gallery`.`category` = `category`.`id` AND 
      `gallery`.`website` = `category`.`website` 
WHERE `gallery`.`website` = 5 

2)

SELECT * 
FROM `gallery` 
    JOIN `category` 
     ON 
      `gallery`.`category` = `category`.`id` AND 
      `category`.`website` = 5 
WHERE `gallery`.`website` = 5 

3)

SELECT * 
FROM `gallery` 
    JOIN (
     SELECT * 
     FROM `category` 
     WHERE `website` = 5 
    ) `category` 
     ON `gallery`.`category` = `category`.`id` 
WHERE `gallery`.`website` = 5 
+0

性能取决于列上是否有索引。 – Barmar

+0

索引:画廊(网站,类别),类别(网站) – Craft

当使用内部联接,所有三个是语义上等同。

我更喜欢第一种方法,因为它使join变得明确,并将连接的条件放在一个地方。其他人冒着在查询的不同部分更改常量可能会对连接产生意想不到的影响的风险。

最后一个,使用子查询可能会有一些性能影响。 MySQL倾向于实现子查询。因此,表现可能会更糟糕。

编辑:

书面,他们是用left outer join相同,但会不同与right outer join或者如果where条件为上gallery

在外部联接中,on子句中的筛选器不会影响第一个表中的总体。连接的逻辑是“如果匹配时返回一行,如果根本不匹配”外连接“表中的值,则返回该行”。另一方面,where确实在连接之后进行过滤。

+0

如果我想使用外部JOIN?如果有些画廊没有类别? – Craft

+0

代码的第一个版本是如何工作的?它是否从网站5,所有类别,然后加入他们所有的galeries?或者它需要从网站5的画廊和网站5的类别,然后加入?它不是比第二个版本慢吗? – Craft

+0

@Craft。 。 。它们的工作方式取决于MySQL如何决定如何处理连接。一个合理的方法是找到gallery中的所有行,其中'website'是5,然后进行连接。但这取决于指标。这三者在所有情况下可能都没有相同的执行计划。 –

查询1和2与性能完全相同。查询3将显着变慢。当然,查询1和2的性能取决于索引。您应该在表website的表gallery上创建索引,并在category的表id,website的列上创建索引。

+0

('website','id')是表'category'中的一个唯一索引,与表'gallery'相同。这可以吗?如果我在表'gallery'上添加('website','category')INDEX,会有帮助吗?只是为了让一个类别的所有画廊更快? – Craft

+0

如果唯一索引是(website,id),则切换条件顺序(category.webiste first)。在画廊里没关系。 – sajushko