關於oracle中的半連線

dbhelper發表於2014-11-26

表的連線在sql語句中尤為重要。外連線,內連線,半連線,反連線等等各種連線,看似簡單的一個連線裡面還是有不少的細節的。對於sql調優來說也是很重要的。
像下面的形式的sql就屬於半連線,使用了in子句,對於exists的實現也是屬於半連線。

--in半連線
SQL> select dname from dept dept where deptno in (select deptno from emp emp);

DNAME
--------------
RESEARCH
SALES
ACCOUNTING

--exists半連線

SQL> select dname from dept dept where exists (select null from emp emp where emp.deptno=dept.deptno)
  2  /

DNAME
--------------
RESEARCH
SALES
ACCOUNTING

可能對於上面兩種連線大家不以為然,認為把需要用到的表直接放在from子句後效果是一致的,答案也不是肯定的。
比如下面的形式,可能輸出的結果就多了很多。大概14條記錄,但是透過半連線的方式會輸出3行記錄。
SQL> select dept.dname from dept dept,emp empwhere dept.deptno=emp.deptno;
DNAME
--------------
RESEARCH
SALES
SALES
RESEARCH
SALES
SALES
ACCOUNTING
RESEARCH
ACCOUNTING
SALES
RESEARCH
SALES
RESEARCH
ACCOUNTING
14 rows selected.

所以說如果要得到一個相同的輸出結果,還是需要distinct+inner join

SQL> select distinct dept.dname from dept dept,emp emp where dept.deptno=emp.deptno;

DNAME
--------------
ACCOUNTING
RESEARCH
SALES

對於半連線的可替換實現,大體有以下幾種方式
--使用集合

select dept.dname from dept dept,
(select deptno from dept
intersect
select deptno from emp emp)b
where dept.deptno=b.deptno ;

DNAME
--------------
ACCOUNTING
RESEARCH
SALES

--使用any

SQL> select dept.dname from dept dept where deptno=any(select deptno from emp emp);

DNAME
--------------
RESEARCH
SALES
ACCOUNTING

--使用distinct和內連線

SQL> select distinct emp.deptno from dept dept,emp emp
    where dept.deptno=emp.deptno;
    DEPTNO
----------
        30
        20
        10
SQL> select distinct dept.deptno from dept dept,emp emp
        where dept.deptno=emp.deptno;
    DEPTNO
----------
        30
        20
        10

大體說了下關於半連線的一些實現,可能在實際的使用中,最直觀的感受還是透過執行計劃來看到。
啟用了半連線,在執行計劃中會有semi的字樣。
關於oracle中的半連線

也可以手動指定不需要走半連線。使用Hint no_semijoin
關於oracle中的半連線

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8494287/viewspace-1346962/,如需轉載,請註明出處,否則將追究法律責任。

相關文章