我经常看到类似......
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')
在查询中查询是否可以?是“内部查询”吗? “子查询”?是否算作三个查询(我的例子)?如果这样做不好......我怎么能改写我的例子?
答案 0 :(得分:3)
你的榜样也不错。最大的问题通常来自于存在所谓的“相关子查询”的情况。那时子查询依赖于外部查询的列。这些特别糟糕,因为子查询实际上需要为潜在结果中的每一行重新运行。
您可以使用连接和GROUP BY
重写子查询,但正如您所知,性能可能会有所不同,尤其是取决于您的RDBMS。
答案 1 :(得分:3)
它因数据库而异,特别是如果比较的列是
...,但通常如果您的查询未使用加入的表中的列,则应使用IN
或EXISTS
:
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 BY
或DISTINCT
来获取唯一值的结果集 - 这会在您查看查询费用时花费您的成本。
虽然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。