我是一个老派的MySQL用户,总是更喜欢JOIN而不是子查询。但是现在每个人都用子查询,我讨厌它;我不知道为什么。

我缺乏理论知识来判断是否有任何不同。子查询是否与JOIN一样好,因此没有什么可担心的?


当前回答

子查询通常用于将单行作为原子值返回,不过它们也可以用于用IN关键字比较多行之间的值。在SQL语句中几乎任何有意义的地方都允许使用它们,包括目标列表、WHERE子句等等。一个简单的子查询可以用作搜索条件。例如,在一对表之间:

SELECT title 
FROM books 
WHERE author_id = (
    SELECT id 
    FROM authors 
    WHERE last_name = 'Bar' AND first_name = 'Foo'
);

注意,在子查询的结果上使用普通值操作符要求只返回一个字段。如果你想检查一个值是否存在于一组其他值中,请使用in:

SELECT title 
FROM books 
WHERE author_id IN (
    SELECT id FROM authors WHERE last_name ~ '^[A-E]'
);

这显然不同于LEFT-JOIN,你只是想连接表a和表B的东西,即使连接条件在表B中没有找到任何匹配的记录,等等。

如果你只是担心速度,你必须检查你的数据库,写一个好的查询,看看是否有显著的性能差异。

其他回答

在旧Mambo CMS的一个非常大的数据库上运行:

SELECT id, alias
FROM
  mos_categories
WHERE
  id IN (
    SELECT
      DISTINCT catid
    FROM mos_content
  );

0秒

SELECT
  DISTINCT mos_content.catid,
  mos_categories.alias
FROM
  mos_content, mos_categories
WHERE
  mos_content.catid = mos_categories.id;

~ 3秒

EXPLAIN说明它们检查的行数完全相同,但其中一个需要3秒,另一个几乎是即时的。这个故事的寓意?如果性能很重要(什么时候不重要?),尝试多种方法,看看哪一种最快。

和…

SELECT
  DISTINCT mos_categories.id,
  mos_categories.alias
FROM
  mos_content, mos_categories
WHERE
  mos_content.catid = mos_categories.id;

0秒

同样,结果相同,检查的行数相同。我猜是DISTINCT mos_content。catid比DISTINCT mos_categories需要更长的时间来计算。id。

子查询能够动态地计算聚合函数。 例如,找到这本书的最低价格,并得到所有以这个价格出售的书。 1)使用子查询:

SELECT titles, price
FROM Books, Orders
WHERE price = 
(SELECT MIN(price)
 FROM Orders) AND (Books.ID=Orders.ID);

2)使用join

SELECT MIN(price)
     FROM Orders;
-----------------
2.99

SELECT titles, price
FROM Books b
INNER JOIN  Orders o
ON b.ID = o.ID
WHERE o.price = 2.99;

在大多数情况下,join比子查询快,子查询比子查询快的情况非常罕见。

在join中,RDBMS可以为您的查询创建一个更好的执行计划,并可以预测应该加载哪些数据来处理并节省时间,不像子查询,它将运行所有的查询并加载所有的数据来进行处理。

子查询的好处是它们比join更可读:这就是为什么大多数新学习SQL的人更喜欢它们;这是简单的方法;但是当涉及到性能时,join在大多数情况下更好,尽管它们也不难读。

现在,许多dbs都可以优化子查询和连接。因此,您只需使用explain检查您的查询,看看哪个更快。如果在性能上没有太大的差异,我更喜欢使用子查询,因为它们简单,更容易理解。

我不是关系数据库专家,所以对此持保留态度。

子查询与连接的一般思想是较大查询的求值路径。

为了执行较大的查询,必须首先执行每个子查询,然后将结果集存储为与较大查询交互的临时表。

这个临时表没有索引,因此,任何比较都需要扫描整个结果集。

相反,当您使用连接时,所有索引都在使用中,因此,比较需要遍历索引树(或哈希表),这在速度方面成本要低得多。

现在,我不知道最流行的关系引擎的新版本是否在反向执行求值,只是将必要的元素加载到临时表中,作为优化方法。