【转】oracle连接查询详解
转自:http://blog.csdn.net/indexman/article/details/7768811
连接查询是数据库查询语句中使用频率很高的查询方式,下面根据Oracle提供的官方文档学习一下连接查询:
一 ??Equijoins 等值连接:
? ? ?等值连接是条件连接在连接运算符为“=”号时的特例。(相对于非等值连接,如:between...and条件)[sql]?view plaincopy?- SQL>?select?e.employee_id,?e.last_name,??
- ??2???????????????????e.department_id,?d.department_id,??
- ??3???????????????????d.location_id??
- ??4??from???employees?e,?departments?d??
- ??5??where??e.department_id?=?d.department_id;??
- EMPLOYEE_ID?LAST_NAME??DEPARTMENT_ID?DEPARTMENT_ID?LOCATION_ID??
- -----------?-------------------------?-------------????????-------------?????-----------??
- ????????198??????????????OConnell??????????????????????????????50???????????????????????????50?????????1500??
- ????????199??????????????Grant?????????????????????????????????????50????????????????????????????50?????????1500??
- ????????200??????????????Whalen????????????????????????????????10????????????????????????????10??????????1700??
- ????????201??????????????Hartstein??????????????????????????????20????????????????????????????20?????????1800??
- ......??
?
?
二 ? ?Self?? joins ?自连接:
自连接(self join)是SQL语句中经常要用的连接方式,使用自连接可以将自身表的一个镜像当作另一个表来对待,从而能够得到一些特殊的数据。
e.g.
?
[sql] view plaincopy?- SELECT?e1.last_name||'?works?for?'||e2.last_name???
- ???"Employees?and?Their?Managers"??
- ???FROM?employees?e1,?employees?e2???
- ???WHERE?e1.manager_id?=?e2.employee_id??
- ??????AND?e1.last_name?LIKE?'R%'??
- ???ORDER?BY?e1.last_name;??
- ??
- Employees?and?Their?Managers?????
- -------------------------------??
- Rajs?works?for?Mourgos??
- Raphaely?works?for?King??
- Rogers?works?for?Kaufling??
- Russell?works?for?King??
? ??If two tables in a join query have no join condition, then Oracle Database returns their?Cartesian product.
? ? 如果2个表连接查询而没有连接条件,则oracle返回他们的笛卡尔积。即oracle返回一个表里每一行与另一个表每一行的组合(15 X 4)。
e.g.
?
[sql]?view plaincopy?- SCOTT@orcl>?select?count(1)?from?emp;??
- ??
- ??COUNT(1)??
- ----------??
- ????????15??
- SCOTT@orcl>?select?count(1)?from?dept;??
- ??
- ??COUNT(1)??
- ----------??
- ?????????4??
- SCOTT@orcl>?select?count(1)?from?emp,?dept;??
- ??
- ??COUNT(1)??
- ----------??
- ????????60??
?
四 ?Inner Joins ?内连接:
??? ?An inner join (sometimes called a simple join) is a join of two or more tables that returns only those rows that satisfy the join condition.
? ? ?内连接也叫简单连接,是2个或更多表的关联并且仅返回那些满足连接条件的行。
e.g.
?
[html]?view plaincopy?- <p?style="font-weight:?bold;?font-size:?18px;"></p><pre?name="code"?class="sql"><span?style="font-size:12px;">select?e.employee_id,?e.last_name,??
- ????????????????e.department_id,?d.department_id,??
- ??????????????????d.location_id??
- FROM???employees?e?JOIN?departments?d??
- ?ON??e.department_id?=?d.department_id;</span></pre><pre?name="code"?class="html"></pre>??
?
?
五 ??Outer joins 外连接:
? 简单连接的扩展。分为左外连接(Left ?outer joins)、右外连接(Right ?outer joins)、全外连接(Full ?outer ?joins)
?和Partitioned Outer Joins(分区外连接,用于数据仓库)
Listing 1:
?
SELECT d.department_id, e.last_name[sql] view plaincopy?
- FROM?departments?d?LEFT?OUTER?JOIN?employees?e??
- ON?d.department_id?=?e.department_id??
- ORDER?BY?d.department_id,?e.last_name;??
另外一种写法:
?
[sql] view plaincopy?- SELECT?d.department_id,?e.last_name??
- ???FROM?departments?d,?employees?e??
- ???WHERE?d.department_id?=?e.department_id(+)??
- ???ORDER?BY?d.department_id,?e.last_name;??
?
Oracle 官方推荐使用第一种写法。
Listing ?2:
?
[sql] view plaincopy?- SELECT?d.department_id,?e.last_name??
- ???FROM?departments?d?RIGHT?OUTER?JOIN?employees?e??
- ???ON?d.department_id?=?e.department_id??
- ???ORDER?BY?d.department_id,?e.last_name;??
- ??
- DEPARTMENT_ID?LAST_NAME??
- -------------?-------------------------??
- .?.?.??
- ??????????110?Higgins??
- ??????????110?Gietz??
- ??????????????Grant??
- ??????????????Zeuss??
?
Listing ?3:?
?
[sql] view plaincopy?- SELECT?d.department_id?as?d_dept_id,?e.department_id?as?e_dept_id,??
- ??????e.last_name??
- ???FROM?departments?d?FULL?OUTER?JOIN?employees?e??
- ???ON?d.department_id?=?e.department_id??
- ???ORDER?BY?d.department_id,?e.last_name;??
- ??
- ?D_DEPT_ID??E_DEPT_ID?LAST_NAME??
- ----------?----------?-------------------------??
- ??.?.?.??
- ???????110????????110?Gietz??
- ???????110????????110?Higgins??
- ??.?.?.??
- ???????260??
- ???????270??
- ??????????????????999?Zeuss??
- ??????????????????????Grant??
更好的写法,使用USING clause
?
?
[sql] view plaincopy?- SELECT?department_id?AS?d_e_dept_id,?e.last_name??
- ???FROM?departments?d?FULL?OUTER?JOIN?employees?e??
- ???USING?(department_id)??
- ???ORDER?BY?department_id,?e.last_name;??
- ??
- D_E_DEPT_ID?LAST_NAME??
- -----------?-------------------------??
- ??.?.?.??
- ????????110?Higgins??
- ????????110?Gietz??
- ??.?.?.??
- ????????260??
- ????????270??
- ????????999?Zeuss??
- ????????????Grant??
?
?
Listing ?4:
?
[sql] view plaincopy?- CREATE?TABLE?inventory?(time_id????DATE,??
- ????????????????????????product????VARCHAR2(10),??
- ????????????????????????quantity???NUMBER);??
- ??
- INSERT?INTO?inventory?VALUES?(TO_DATE('01/04/01',?'DD/MM/YY'),?'bottle',?10);??
- INSERT?INTO?inventory?VALUES?(TO_DATE('06/04/01',?'DD/MM/YY'),?'bottle',?10);??
- INSERT?INTO?inventory?VALUES?(TO_DATE('01/04/01',?'DD/MM/YY'),?'can',?10);??
- INSERT?INTO?inventory?VALUES?(TO_DATE('04/04/01',?'DD/MM/YY'),?'can',?10);??
- ??
- SELECT?times.time_id,?product,?quantity?FROM?inventory???
- ???PARTITION?BY??(product)???
- ???RIGHT?OUTER?JOIN?times?ON?(times.time_id?=?inventory.time_id)???
- ???WHERE?times.time_id?BETWEEN?TO_DATE('01/04/01',?'DD/MM/YY')???
- ??????AND?TO_DATE('06/04/01',?'DD/MM/YY')???
- ???ORDER?BY??2,1;???
- ??
- TIME_ID???PRODUCT??????QUANTITY??
- ---------?----------?----------??
- 01-APR-01?bottle?????????????10??
- 02-APR-01?bottle??
- 03-APR-01?bottle??
- 04-APR-01?bottle??
- 05-APR-01?bottle??
- 06-APR-01?bottle?????????????10??
- 06-APR-01?bottle??????????????8??
- 01-APR-01?can????????????????10??
- 01-APR-01?can????????????????15??
- 02-APR-01?can??
- 03-APR-01?can??
- 04-APR-01?can????????????????10??
- 04-APR-01?can????????????????11??
- 05-APR-01?can??
- 06-APR-01?can??
- ??
- 15?rows?selected.??
?
?
更好的写法:
?
[sql] view plaincopy?- SELECT?time_id,?product,?LAST_VALUE(quantity?IGNORE?NULLS)???
- ???OVER?(PARTITION?BY?product?ORDER?BY?time_id)?quantity???
- ???FROM?(?SELECT?times.time_id,?product,?quantity???
- ?????????????FROM?inventory?PARTITION?BY??(product)???
- ????????????????RIGHT?OUTER?JOIN?times?ON?(times.time_id?=?inventory.time_id)???
- ???WHERE?times.time_id?BETWEEN?TO_DATE('01/04/01',?'DD/MM/YY')???
- ??????AND?TO_DATE('06/04/01',?'DD/MM/YY'))???
- ???ORDER?BY??2,1;???
- ??
- TIME_ID???PRODUCT??????QUANTITY??
- ---------?----------?----------??
- 01-APR-01?bottle?????????????10??
- 02-APR-01?bottle?????????????10??
- 03-APR-01?bottle?????????????10??
- 04-APR-01?bottle?????????????10??
- 05-APR-01?bottle?????????????10??
- 06-APR-01?bottle??????????????8??
- 06-APR-01?bottle??????????????8??
- 01-APR-01?can????????????????15??
- 01-APR-01?can????????????????15??
- 02-APR-01?can????????????????15??
- 03-APR-01?can????????????????15??
- 04-APR-01?can????????????????11??
- 04-APR-01?can????????????????11??
- 05-APR-01?can????????????????11??
- 06-APR-01?can????????????????11??
- ??
- 15?rows?selected.??
?
?
?六???Anti-joins 反连接:
??返回不满足子查询条件(NOT IN)的左表记录。
e.g.
?
[sql] view plaincopy?- SELECT?*?FROM?employees???
- ???WHERE?department_id?NOT?IN???
- ???(SELECT?department_id?FROM?departments???
- ???????WHERE?location_id?=?1700)??
- ???ORDER?BY?last_name;??
?
??七?? Semi-joins 半连接:
? ?返回匹配exists子查询的左侧没有重复的行。
e.g.
?
[sql] view plaincopy?- SELECT?*?FROM?departments???
- ???WHERE?EXISTS???
- ???(SELECT?*?FROM?employees???
- ???????WHERE?departments.department_id?=?employees.department_id???
- ???????AND?employees.salary?>?2500)??
- ???ORDER?BY?department_name;??