Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 内部查询是否正常?_Sql_Subquery - Fatal编程技术网

Sql 内部查询是否正常?

Sql 内部查询是否正常?,sql,subquery,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 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')
可以在查询中使用查询吗?是内部查询吗?子查询?在我的示例中,它是否算作三个查询?如果这样做不好。。。如何重写我的示例?

您可以加入联系人表:

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没有给它太多选择。

您的示例还不错。最大的问题通常来自存在所谓的相关子查询的情况。此时子查询依赖于外部查询中的列。这些情况尤其糟糕,因为潜在结果中的每一行都需要有效地重新运行子查询


您可以使用联接和分组方式重写子查询,但由于性能的不同,尤其取决于您的RDBMS。

这种查询最常用的术语是子查询。使用它们本身并没有什么错,可以让你的生活更轻松。但是,通常可以通过重写查询和子查询以使用联接来提高性能,因为服务器可以找到优化

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

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版本会更好,因为您可以避免对联系人进行两次选择查询,而是选择JOIN


请参阅主题上的。

它因数据库而异,尤其是在比较列时

是否索引 是否可以为空 …,但通常情况下,如果您的查询未使用连接到的表中的列,则应使用IN或EXISTS:

如果子表有多个与父表记录相关的记录,则使用内部或外部联接可以膨胀记录。如果您需要这些信息,这很好,但如果不需要,则需要使用GROUP BY或DISTINCT来获得唯一值的结果集,这可能会在您查看查询成本时产生成本

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

这是一个好问题。无论使用内部查询还是联接,SQL查询引擎通常都会输出类似的SQL。尝试用两种不同的方式编写查询—比如使用内部联接进行重写,然后查看两种执行计划。例如,如果在Microsoft SQL Server Management Studio中显示两个查询的估计执行计划,查询引擎甚至会向您显示每个查询所代表的总工作负载的百分比,这样您就可以自己查看哪些可能是最有效的,以及调整索引等。您将需要一个分组依据或不同的方法来获得相同的结果。通过使用联接,您可能最终得到同一事件的多个结果。您需要一个GROUP By或DISTINCT来获得相同的结果。通过使用联接,最终可能会得到同一事件的多个结果:
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 )