内部查询是否正常?

时间:2011-07-05 16:49:12

标签: sql subquery

我经常看到类似......

SELECT events.id, events.begin_on, events.name
  FROM events
 WHERE events.user_id IN ( SELECT contacts.user_id 
                             FROM contacts 
                            WHERE contacts.contact_id = '1')
   OR events.user_id IN ( SELECT contacts.contact_id 
                            FROM contacts 
                           WHERE contacts.user_id = '1')

在查询中查询是否可以?是“内部查询”吗? “子查询”?是否算作三个查询(我的例子)?如果这样做不好......我怎么能改写我的例子?

4 个答案:

答案 0 :(得分:3)

你的榜样也不错。最大的问题通常来自于存在所谓的“相关子查询”的情况。那时子查询依赖于外部查询的列。这些特别糟糕,因为子查询实际上需要为潜在结果中的每一行重新运行。

您可以使用连接和GROUP BY重写子查询,但正如您所知,性能可能会有所不同,尤其是取决于您的RDBMS。

答案 1 :(得分:3)

它因数据库而异,特别是如果比较的列是

  • 是否已编入索引
  • nullable or not

...,但通常如果您的查询未使用加入的表中的列,则应使用INEXISTS

SELECT e.id, e.begin_on, e.name
  FROM EVENTS e
 WHERE EXISTS (SELECT NULL
                 FROM CONTACTS c 
                WHERE ( c.contact_id = '1' AND c.user_id = e.user_id )
                   OR ( c.user_id = '1' AND c.contact_id = e.user_id )

如果子表具有多个与父表记录相关的记录,则使用JOIN(INNER或OUTER)可以使记录膨胀。如果您需要这些信息,那就没问题,但如果不需要,那么您需要使用GROUP BYDISTINCT来获取唯一值的结果集 - 这会在您查看查询费用时花费您的成本。

EXISTS

虽然EXISTS子句看起来像相关子查询,但它们不会这样执行(RBAR:Row By Agonizing Row)。 EXISTS根据提供的条件返回一个布尔值,并在第一个实例上退出为true - 这可以使它在处理子表中的重复项时比IN更快。

答案 2 :(得分:1)

您可以JOIN改为联系人表格:

SELECT events.id, events.begin_on, events.name
FROM events
JOIN contacts
ON (events.user_id = contacts.contact_id OR events.user_id = contacts.user_id)
WHERE events.user_id = '1'
GROUP BY events.id  
-- exercise: without the GROUP BY, how many duplicate rows can you end up with?

这会将以下问题留给数据库:“我们应该查看所有联系人表格并查找各列中的所有'1,还是做其他事情?”你的原始SQL没有给它多少选择。

答案 3 :(得分:1)

此类查询最常见的术语是“子查询”。使用它们本身没有任何错误,可以让你的生活更轻松。但是,通常可以通过重写具有子查询的查询来改进性能,因为服务器可以找到优化。

在您的示例中,执行三个查询:主SELECT查询和两个SELECT子查询。

SELECT events.id, events.begin_on, events.name
FROM events
JOIN contacts
ON (events.user_id = contacts.contact_id OR events.user_id = contacts.user_id)
WHERE events.user_id = '1'
GROUP BY events.id

在您的情况下,我相信JOIN版本会更好,因为您可以避免对联系人进行两次SELECT查询,而是选择JOIN。

请参阅主题上的mysql docs