问题描述
嗨,
在许多网站和问题解答社区 (例如Quora等) 中,我读到有关非相关子查询和共同相关子查询之间的区别,基本区别是首先共同相关执行外部查询,然后是子查询
示例
但是不相关的查询首先执行内部查询,然后执行外部查询,例如
所以我的问题是
1.Oracle如何具有判断查询是共同关联还是非共同关联的智能?
2.对于所有类型的子查询,它是否遵循相同的select语句执行过程,例如From cluse excution,然后Where子句执行,然后按顺序分组?
在许多网站和问题解答社区 (例如Quora等) 中,我读到有关非相关子查询和共同相关子查询之间的区别,基本区别是首先共同相关执行外部查询,然后是子查询
示例
select * from departments dep where employee_id in (select employee_id from employees emp where emp.employee_id = dep.employee_id)复制
但是不相关的查询首先执行内部查询,然后执行外部查询,例如
select * from departments where employee_id in (select employee_id from employees);复制
所以我的问题是
1.Oracle如何具有判断查询是共同关联还是非共同关联的智能?
2.对于所有类型的子查询,它是否遵循相同的select语句执行过程,例如From cluse excution,然后Where子句执行,然后按顺序分组?
专家解答
相关与不相关与Oracle数据库如何处理SQL无关。只是您是否在子查询中包含外部查询中的列。
如果子查询中的一个或多个父表中的列与子查询相关。所以:
是相关的,因为dep.employee在嵌套查询中。鉴于:
不相关,因为子查询中没有对部门的引用。
Logically数据库执行外部查询,然后在内部查询中找到匹配的行。但在实践中,优化器可以重写它,以不同的方式处理它们。
通常,优化器会尝试首先访问具有最小结果集的表。例如,下面我创建了两个表。一个有10行,一个有1,000。哪个表是父表,哪个是子查询都没关系。优化器首先选择访问较小的表:
在这两种情况下,它都将子查询转换为联接。由于这种重写,它可能会以不同于您预期的顺序访问表。整个语句仍将首先处理从句,然后处理where等。但是你不能仅仅通过查看就确定子查询是如何进入这个的。
进一步阅读: 使用子查询:
http://docs.oracle.com/database/122/SQLRF/Using-Subqueries.htm#SQLRF52357
如果子查询中的一个或多个父表中的列与子查询相关。所以:
select * from departments dep where employee_id in (select employee_id from employees emp where emp.employee_id = dep.employee_id)复制
是相关的,因为dep.employee在嵌套查询中。鉴于:
select * from departments where employee_id in (select employee_id from employees);复制
不相关,因为子查询中没有对部门的引用。
Logically数据库执行外部查询,然后在内部查询中找到匹配的行。但在实践中,优化器可以重写它,以不同的方式处理它们。
通常,优化器会尝试首先访问具有最小结果集的表。例如,下面我创建了两个表。一个有10行,一个有1,000。哪个表是父表,哪个是子查询都没关系。优化器首先选择访问较小的表:
create table t1 as select rownum x, 'xxxx' y from dual connect by level <= 1000; create table t2 as select rownum x, 'yyyy' y from dual connect by level <= 10; exec dbms_stats.gather_table_stats(user, 't1'); exec dbms_stats.gather_table_stats(user, 't2'); set serveroutput off alter session set statistics_level = all; select * from t1 where t1.x in (select t2.x from t2); select * from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST')); PLAN_TABLE_OUTPUT EXPLAINED SQL STATEMENT: ------------------------ select * from t1 where t1.x in (select t2.x from t2) Plan hash value: 1167709942 ------------------------------------- | Id | Operation | Name | ------------------------------------- | 0 | SELECT STATEMENT | | | 1 | HASH JOIN RIGHT SEMI| | | 2 | TABLE ACCESS FULL | T2 | | 3 | TABLE ACCESS FULL | T1 | ------------------------------------- select * from t2 where t2.x in (select t1.x from t1); select * from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST')); PLAN_TABLE_OUTPUT EXPLAINED SQL STATEMENT: ------------------------ select * from t2 where t2.x in (select t1.x from t1) Plan hash value: 4118005679 ----------------------------------- | Id | Operation | Name | ----------------------------------- | 0 | SELECT STATEMENT | | | 1 | HASH JOIN SEMI | | | 2 | TABLE ACCESS FULL| T2 | | 3 | TABLE ACCESS FULL| T1 | -----------------------------------复制
在这两种情况下,它都将子查询转换为联接。由于这种重写,它可能会以不同于您预期的顺序访问表。整个语句仍将首先处理从句,然后处理where等。但是你不能仅仅通过查看就确定子查询是如何进入这个的。
进一步阅读: 使用子查询:
http://docs.oracle.com/database/122/SQLRF/Using-Subqueries.htm#SQLRF52357
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。