日期:2014-05-16  浏览次数:20503 次

ORACLE 运算
集合运算
集合运算
   集合运算组合两个或多个部分查询的结果到一个结果中。包含集合运算的查询称为复合查询。

Operator		Returns

UNION(联合)		由每个查询选择的所有不同的行(无重复值)
UNION ALL		由每个查询选择的所有的行,包括所有重复的行
INTERSECT(交叉)		由两个查询选择的所有不同的行
MINUS			由第一个查询选择的所有不同的行


   所有的集合运算与等号的优先级相同,如果SQL语句包含多个集合运算并且没有圆括号明确地指定另一个顺序,Oracle服务器将以从左到右的顺序计算。你应该使用圆括号来明确地指定带另外的集合运算的INTERSECT (相交) 运算查询中的赋值顺序。

    注:在幻灯片中,图中的亮色代表查询结果。

    INTERSECT (相交) 和MINUS (相减) 运算不是ANSI SQL-99兼容的,他们是Oracle特定的。


在下面要用到的表:
:: EMPLOYEES: 提供所有在职雇员当前的详细资料
:: JOB_HISTORY:当一个雇员改变工作时,记录他的以前的工作的开始日期和结束日期、
   departmentID和job ID的详细资料

SQL> desc employees;
 名称                                      是否为空? 类型
 ----------------------------------------- -------- -------------
 EMPLOYEE_ID                               NOT NULL NUMBER(6)
 FIRST_NAME                                         VARCHAR2(20)
 LAST_NAME                                 NOT NULL VARCHAR2(25)
 EMAIL                                     NOT NULL VARCHAR2(25)
 PHONE_NUMBER                                       VARCHAR2(20)
 HIRE_DATE                                 NOT NULL DATE
 JOB_ID                                    NOT NULL VARCHAR2(10)
 SALARY                                             NUMBER(8,2)
 COMMISSION_PCT                                     NUMBER(2,2)
 MANAGER_ID                                         NUMBER(6)
 DEPARTMENT_ID                                      NUMBER(4)


QL> desc job_history
名称                   是否为空?    类型
---------------------- -------- -------------
EMPLOYEE_ID            NOT NULL NUMBER(6)
START_DATE             NOT NULL DATE
END_DATE               NOT NULL DATE
JOB_ID                 NOT NULL VARCHAR2(10)
DEPARTMENT_ID                   NUMBER(4)



[b]联合运算[/b]

联合(UNION) 运算从两个查询返回除去重复值后的结果

UNION(联合)运算
UNION运算返回所有由任一查询选择的行。用UNION运算从多表返回所有行,但除去任何重复的行。

原则./././././
:: 被选择的列数和列的数据类型必须是与所有用在查询中的SELECT语句一致。列的名字不必相同。
:: 联合运算在所有被选择的列上进行。
:: 在做重复检查的时候不忽略空(NULL)值。././././
:: IN运算有比UNION运算高的优先级。
:: 在默认情况下,输出以SELECT子句的第一列的升序排序。./././././



[b]使用联合集合运算[/b]
    
   显示当前和以前所有雇员的工作岗位。每个雇员仅显示一次

SELECT employee_id, job_id
FROM employees
UNION
SELECT employee_id, job_id
FROM job_history;

使用联合集合(UNION SET)运算
       联合运算消除重复记录,如果有相同的记录同时出现在EMPLOYEES和JOB_HISTORY表中,该记录只显示一次,观察幻灯片的输出显示雇员号为200的雇员的雇员号虽然显示了两次,但每一行的JOB_ID是不同的。

考虑下面的例子:
SELECT employee_id, job_id, department_id
FROM employees
UNION
SELECT employee_id, job_id, department_id
FROM job_history;


EMPLOYEE_ID	JOB_ID		DEPARTMENT_ID
100
200	 	AC_ACCOUNT	90
200		AD_ASST		10
200		AD_ASST		90

...
600

使用联合集合(UNION SET)运算 (续)
    在前面的输出中,雇员200出现了3次,为什么?注意雇员200的DEPARTMENT_ID值,一行是90,另一行是10,第三行是90,因为这些job_id和department_id的唯一组合,对于每行的雇员200是唯一的,因此他们是不重复的。
   
    观察输出以SELECT子句的第一列的升序排序,即以EMPLOYEE_ID排序。


[b]全联合运算[/b]

    全联合(UNION ALL) 运算从两个查询返回包括所有重复值的结果


全联合(UNION ALL)运算
用全联合运算从多个查询中返回所有行。

原则	./././././././././
:: 和联合不同,重复的行不被过滤,并且默认情况下输出不排序。
:: 不能使用DISTINCT关键字。

   注:除了上面的两点,UNION ALL的原则与UNION相同。


[b]使用全联合运算[/b]

    显示当前和以前所有雇员所在的部门

SELECT employee_id, job_id, department_id
FROM employees
UNION ALL
SELECT employee_id, job_id, department_id
FROM job_history
ORDER BY employee_id;


EMPLOYEE_ID	JOB_ID		DEPARTMENT_ID
100
200		AD_ASST		10
200		AD_ASST		90
200	 	AC_ACCOUNT	90

...
600

[b]
全联合(UNION ALL)运算 (续)[/b]
    在例子中,有30行被选择,两个表组合到共30行中,全联合运算不会消除重复的行,在幻灯片中重复的行被突出显示,联合返回任一查询所选择的所有不重复的行,而全联合返回任一查询所选择的所有行,包括所有重复。

现在用联合子句来写:
SELECT employee_id, job_id,department_id 
FROM employees 
UNION 
SELECT employee_id, job_id,department_id 
FROM job_history 
ORDER BY employee_id;

上面的查询返回29行,这是因为下面的行被除去了(因为它是一个重复行):
176	SA_REP		80


[b]
相交运算
[/b]
   相交(INTERSECT) 运算返回多个查询中所有相同的行

相交运算
      用相交运算返回多个查询中所有的公共行。

原则		./././.列数和数据类型
:: 在查询中被 SELECT 语句选择的列数和数据类型必须与在查询中所使用的所有的 SELTCT 语句中的   一样,但列的名字不必一样。
:: 颠倒相交的表的排序不改变结果。
:: 相交不忽略空值。

[b]使用相交运算[/b]

      显示雇员表的employee_ID 和job_ID,这些雇员当前所做的工作是以前他们做过一端时间,后来有变化,现在又在做的工作。

SQL> SELECT employee_id, job_id
  2  FROM employees
  3  INTERSECT
  4  SELECT employee_id, job_id
  5  FR