ORACLE 运算

来源:互联网 发布:盘古网络永清县种养殖 编辑:程序博客网 时间:2024/05/29 14:47
集合运算 
集合运算 
   集合运算组合两个或多个部分查询的结果到一个结果中。包含集合运算的查询称为复合查询。 

Sql代码  收藏代码
  1. Operator        Returns  
  2.   
  3. UNION(联合)       由每个查询选择的所有不同的行(无重复值)  
  4. UNION ALL       由每个查询选择的所有的行,包括所有重复的行  
  5. INTERSECT(交叉)       由两个查询选择的所有不同的行  
  6. MINUS           由第一个查询选择的所有不同的行  
  7.   
  8.   
  9.    所有的集合运算与等号的优先级相同,如果SQL语句包含多个集合运算并且没有圆括号明确地指定另一个顺序,Oracle服务器将以从左到右的顺序计算。你应该使用圆括号来明确地指定带另外的集合运算的INTERSECT (相交) 运算查询中的赋值顺序。  
  10.   
  11.     注:在幻灯片中,图中的亮色代表查询结果。  
  12.   
  13.     INTERSECT (相交) 和MINUS (相减) 运算不是ANSI SQL-99兼容的,他们是Oracle特定的。  
  14.   
  15.   
  16. 在下面要用到的表:  
  17. :: EMPLOYEES: 提供所有在职雇员当前的详细资料  
  18. :: JOB_HISTORY:当一个雇员改变工作时,记录他的以前的工作的开始日期和结束日期、  
  19.    departmentID和job ID的详细资料  
  20.   
  21. SQL> desc employees;  
  22.  名称                                      是否为空? 类型  
  23.  ----------------------------------------- -------- -------------  
  24.  EMPLOYEE_ID                               NOT NULL NUMBER(6)  
  25.  FIRST_NAME                                         VARCHAR2(20)  
  26.  LAST_NAME                                 NOT NULL VARCHAR2(25)  
  27.  EMAIL                                     NOT NULL VARCHAR2(25)  
  28.  PHONE_NUMBER                                       VARCHAR2(20)  
  29.  HIRE_DATE                                 NOT NULL DATE  
  30.  JOB_ID                                    NOT NULL VARCHAR2(10)  
  31.  SALARY                                             NUMBER(8,2)  
  32.  COMMISSION_PCT                                     NUMBER(2,2)  
  33.  MANAGER_ID                                         NUMBER(6)  
  34.  DEPARTMENT_ID                                      NUMBER(4)  
  35.   
  36.   
  37. QL> desc job_history  
  38. 名称                   是否为空?    类型  
  39. ---------------------- -------- -------------  
  40. EMPLOYEE_ID            NOT NULL NUMBER(6)  
  41. START_DATE             NOT NULL DATE  
  42. END_DATE               NOT NULL DATE  
  43. JOB_ID                 NOT NULL VARCHAR2(10)  
  44. DEPARTMENT_ID                   NUMBER(4)  
  45.   
  46.   
  47.   
  48. [b]联合运算[/b]  
  49.   
  50. 联合(UNION) 运算从两个查询返回除去重复值后的结果  
  51.   
  52. UNION(联合)运算  
  53. UNION运算返回所有由任一查询选择的行。用UNION运算从多表返回所有行,但除去任何重复的行。  
  54.   
  55. 原则./././././  
  56. :: 被选择的列数和列的数据类型必须是与所有用在查询中的SELECT语句一致。列的名字不必相同。  
  57. :: 联合运算在所有被选择的列上进行。  
  58. :: 在做重复检查的时候不忽略空(NULL)值。././././  
  59. :: IN运算有比UNION运算高的优先级。  
  60. :: 在默认情况下,输出以SELECT子句的第一列的升序排序。./././././  
  61.   
  62.   
  63.   
  64. [b]使用联合集合运算[/b]  
  65.       
  66.    显示当前和以前所有雇员的工作岗位。每个雇员仅显示一次  
  67.   
  68. SELECT employee_id, job_id  
  69. FROM employees  
  70. UNION  
  71. SELECT employee_id, job_id  
  72. FROM job_history;  
  73.   
  74. 使用联合集合(UNION SET)运算  
  75.        联合运算消除重复记录,如果有相同的记录同时出现在EMPLOYEES和JOB_HISTORY表中,该记录只显示一次,观察幻灯片的输出显示雇员号为200的雇员的雇员号虽然显示了两次,但每一行的JOB_ID是不同的。  
  76.   
  77. 考虑下面的例子:  
  78. SELECT employee_id, job_id, department_id  
  79. FROM employees  
  80. UNION  
  81. SELECT employee_id, job_id, department_id  
  82. FROM job_history;  
  83.   
  84.   
  85. EMPLOYEE_ID JOB_ID      DEPARTMENT_ID  
  86. 100  
  87. 200     AC_ACCOUNT  90  
  88. 200     AD_ASST     10  
  89. 200     AD_ASST     90  
  90.   
  91. ...  
  92. 600  
  93.   
  94. 使用联合集合(UNION SET)运算 (续)  
  95.     在前面的输出中,雇员200出现了3次,为什么?注意雇员200的DEPARTMENT_ID值,一行是90,另一行是10,第三行是90,因为这些job_id和department_id的唯一组合,对于每行的雇员200是唯一的,因此他们是不重复的。  
  96.      
  97.     观察输出以SELECT子句的第一列的升序排序,即以EMPLOYEE_ID排序。  
  98.   
  99.   
  100. [b]全联合运算[/b]  
  101.   
  102.     全联合(UNION ALL) 运算从两个查询返回包括所有重复值的结果  
  103.   
  104.   
  105. 全联合(UNION ALL)运算  
  106. 用全联合运算从多个查询中返回所有行。  
  107.   
  108. 原则  ./././././././././  
  109. :: 和联合不同,重复的行不被过滤,并且默认情况下输出不排序。  
  110. :: 不能使用DISTINCT关键字。  
  111.   
  112.    注:除了上面的两点,UNION ALL的原则与UNION相同。  
  113.   
  114.   
  115. [b]使用全联合运算[/b]  
  116.   
  117.     显示当前和以前所有雇员所在的部门  
  118.   
  119. SELECT employee_id, job_id, department_id  
  120. FROM employees  
  121. UNION ALL  
  122. SELECT employee_id, job_id, department_id  
  123. FROM job_history  
  124. ORDER BY employee_id;  
  125.   
  126.   
  127. EMPLOYEE_ID JOB_ID      DEPARTMENT_ID  
  128. 100  
  129. 200     AD_ASST     10  
  130. 200     AD_ASST     90  
  131. 200     AC_ACCOUNT  90  
  132.   
  133. ...  
  134. 600  
  135.   
  136. [b]  
  137. 全联合(UNION ALL)运算 (续)[/b]  
  138.     在例子中,有30行被选择,两个表组合到共30行中,全联合运算不会消除重复的行,在幻灯片中重复的行被突出显示,联合返回任一查询所选择的所有不重复的行,而全联合返回任一查询所选择的所有行,包括所有重复。  
  139.   
  140. 现在用联合子句来写:  
  141. SELECT employee_id, job_id,department_id   
  142. FROM employees   
  143. UNION   
  144. SELECT employee_id, job_id,department_id   
  145. FROM job_history   
  146. ORDER BY employee_id;  
  147.   
  148. 上面的查询返回29行,这是因为下面的行被除去了(因为它是一个重复行):  
  149. 176 SA_REP      80  
  150.   
  151.   
  152. [b]  
  153. 相交运算  
  154. [/b]  
  155.    相交(INTERSECT) 运算返回多个查询中所有相同的行  
  156.   
  157. 相交运算  
  158.       用相交运算返回多个查询中所有的公共行。  
  159.   
  160. 原则      ./././.列数和数据类型  
  161. :: 在查询中被 SELECT 语句选择的列数和数据类型必须与在查询中所使用的所有的 SELTCT 语句中的   一样,但列的名字不必一样。  
  162. :: 颠倒相交的表的排序不改变结果。  
  163. :: 相交不忽略空值。  
  164.   
  165. [b]使用相交运算[/b]  
  166.   
  167.       显示雇员表的employee_ID 和job_ID,这些雇员当前所做的工作是以前他们做过一端时间,后来有变化,现在又在做的工作。  
  168.   
  169. SQL> SELECT employee_id, job_id  
  170.   2  FROM employees  
  171.   3  INTERSECT  
  172.   4  SELECT employee_id, job_id  
  173.   5  FROM job_history;  
  174.   
  175. EMPLOYEE_ID JOB_ID  
  176. ----------- ----------  
  177.         176 SA_REP  
  178.         200 AD_ASST  
  179.   
  180.   
  181. 相交运算 (续)  
  182.     在幻灯片的例子中,查询仅返回在两个表的被选择的列中有相同值的记录。  
  183.   
  184.     如果你从EMPLOYEES表添加DEPARTMENT_ID列到SELECT语句中,并且从JOB_HISTORY表添加DEPARTMENT_ID列到SELECT语句中,然后运行该查询,将返回什么?其结果可能是不同的,因为在加入的另一个列中,其值可能是重复的,也可能不重复。  
  185.   
  186. 例子  
  187. SELECT employee_id, job_id, department_id  
  188. FROM employees  
  189. INTERSECT  
  190. SELECT employee_id, job_id, department_id  
  191. FROM job_history;  
  192.   
  193. EMPLOYEE_ID JOB_ID     DEPARTMENT_ID  
  194. ----------- ---------- -------------  
  195.         176 SA_REP                80  
  196.   
  197. 雇员200不再是结果的一部分,因为EMPLOYEES.DEPARTMENT_ID值不同于 JOB_HISTORY.DEPARTMENT_ID值。  
  198.   
  199.   
  200. [b]相减运算 [/b]  
  201.   
  202.     相减(MINUS) 运算返回在第一个查询中而不在第二个查询中的行  
  203.   
  204. 相减运算  
  205.     用相减运算返回由第一个查询返回的行,那些行不出现在第二个查询中 (第一个SELECT语句减第二个SELECT语句)。  
  206.   
  207. 原则  ./././././././  
  208. :: 在查询中被SELECT语句选择的列数和数据类型必须与在查询中所使用的所有的SELTCT语句中的一样    ,但列的名字不必一样。  
  209. :: 对于MINUS运算,在WHERE子句中所有的列都必须在SELECT子句中。  
  210.   
  211. 相减运算  
  212.      
  213.    显示那些从来没有改变过他们的工作的雇员显示那些从来没有改变过他们的工作的雇员ID  
  214.   
  215. SELECT employee_id,job_id  
  216. FROM employees  
  217. MINUS  
  218. SELECT employee_id,job_id  
  219. FROM job_history;  
  220. //由存在于EMPLOYEES表中但不存在于JOB_HISTORY表中的行所表示(结果只是employees表的减少,没有第二个表的记录.)  
  221.   
  222. 相减运算 (续)  
  223.      上述例子中,JOB_HISTORY表的employee_id列和job_id列被从EMPLOYEES表的那些列中减去。结果集显示相减后剩余的雇员,他们由存在于EMPLOYEES表中但不存在于JOB_HISTORY表中的行所表示。这些行是那些从未改变过工作的雇员的记录  
  224.   
  225. 雇员200未出现,因为他换过工作。(即,在第一个,第二个表中都出现了)  
  226.   
  227.   
  228. [b]集合运算的原则[/b]  /././././././  
  229.   
  230. :: 在两个SELECT列表中的表达式必须在数目上和数据类型上相匹配  
  231. :: 可以用圆括号改变执行的顺序  
  232.   
  233. :: ORDER BY子句:  /./././././  
  234.     –只能出现在语句的最后  
  235.     –从第一个SELECT语句接收列名、别名,或者位置记号  
  236.   
  237.   
  238. 集合运算的原则  
  239.   
  240. :: 在两个查询的选择列表中的表达式在数目上和数据类型上必须匹配。使用UNIONUNION ALLINTERSECT和MINUS SET运算的查询,在它们的WHERE子句中必须有与它们的SELECT列表相同的列数和列数据类型。  
  241.   
  242. 例如:  
  243. SELECT employee_id, department_id  
  244. FROM employees  
  245. WHERE (employee_id, department_id)  
  246. IN (SELECT employee_id, department_id  
  247.     FROM employees  
  248.     UNION  
  249.     SELECT employee_id, department_id  
  250.     FROM job_history  
  251. );  
  252.   
  253. :: ORDER BY子句:  
  254.     - 只可以出现在每个语句的末尾  
  255.     - 将接受列、别名或位置记号  
  256.   
  257. :: 列名或别名,如果用在ORDER BY子句中,必须来自第一个SELECT列表。  
  258. :: 集合运算可以用在子查询中。  
  259.   
  260.   
  261.   
  262. [b]Oracle 服务器和集合运算[/b]  
  263.   
  264. :: 除了UNION ALL,重复行自动被清除  
  265. :: 在结果中的列名是第一个查询中出现的列名  /./././  
  266. :: 除了UNION ALL(无排序),默认情况下按升序顺序输出    /././  
  267.   
  268. Oracle服务器和集合运算  
  269.    当一个查询使用集合运算时,除了UNION ALL运算,Oracle服务器会自动消除重复的行。输出中的列名由第一个SELECT语句的列表确定。默认情况下,输出以SELECT子句的第一列的升序排序。  
  270.   
  271.    在一个复合查询的各查询组成部分的选择列表中相应的表达式必须在数目和类型上匹配。如果查询的组成部分选择字符数据,返回值的数据类型被如下决定:  
  272.  :: 如果查询选择的数据类型的值为CHAR,那么,返回值的数据类型也为CHAR。  
  273.  :: 如果查询选择的两者之一或两者的数据类型值为VARCHAR2,那么,返回值的数据类型也是VARCHAR2。  
  274.   
  275.   你可能需要提及,输出以第一个SELECT子句的第一列的升序被排序,然后是第二列,等等。  
  276.   
  277.   
  278.   
  279. 匹配SELECT语句  //凑数  
  280.   
  281.    使用UNION运算,显示所有雇员的department ID、location、和受雇日期  
  282.   
  283.   
  284. SELECT department_id, TO_NUMBER(null) location, hire_date  
  285. FROM employees  
  286. UNION  
  287. SELECT department_id, location_id, TO_DATE(null)  
  288. FROM departments;  
  289.   
  290. DEPARTMENT_ID   LOCATION HIRE_DATE  
  291. ------------- ---------- ----------  
  292.            80            21-4月 -00  
  293.            90       1700  
  294.            90            17-6月 -87  
  295.            90            21-9月 -89  
  296.            90            13-1月 -93  
  297.           100       1700  
  298.           100            16-8月 -94  
  299.           100            17-8月 -94  
  300.           100            28-9月 -97  
  301.           100            30-9月 -97  
  302.           100            07-3月 -98  
  303.   
  304. 匹配SELECT语句  
  305.     由于在两个查询的SELECT列表中的表达式必须在数量上匹配,你可以使用虚拟列和转换函数数据类型来满足该规则。在幻灯片中使用了虚拟列,在第一个查询中的TO_NUMBER函数被用以匹配第二个查询中返回的LOCATION_ID列的数字数据类型,同样地,第二个查询中的TO_DATE函数被用于匹配 第一个查询返回的日期数据类型。  
  306.   
  307. [b]匹配SELECT语句[/b]  
  308.   
  309. :: 使用UNION运算,显示所有雇员的employee ID、job ID 和salary  
  310.   
  311. SELECT employee_id, job_id,salary  
  312. FROM employees  
  313. UNION  
  314. SELECT employee_id, job_id,0  
  315. FROM job_history;  
  316.   
  317. EMPLOYEE_ID JOB_ID         SALARY  
  318. ----------- ---------- ----------  
  319.         192 SH_CLERK         4000  
  320.         193 SH_CLERK         3900  
  321.         194 SH_CLERK         3200  
  322.         195 SH_CLERK         2800  
  323.         196 SH_CLERK         3100  
  324.         197 SH_CLERK         3000  
  325.         198 SH_CLERK         2600  
  326.         199 SH_CLERK         2600  
  327.         200 AC_ACCOUNT          0  
  328.         200 AD_ASST             0  
  329.         200 AD_ASST          4400  
  330.   
  331.   
  332. 匹配SELECT语句:例  
  333.       EMPLOYEES和JOB_HISTORY表中有一些列是公有的;例如,EMPLOYEE_ID, JOB_ID和DEPARTMENT_ID,但如果你想要用UNION运算查询他们以显示EMPLOYEE_ID、JOB_ID和SALARY时,知道薪水仅存在于EMPLOYEES表中吗?  
  334.   
  335.       在幻灯片中的代码例子匹配EMPLOYEES表和JOB_HISTORY表中的EMPLOYEE_ID和JOB_ID列。一个0值被添加到JOB_HISTORY的SELECT语句中以匹配在EMPLOYEES的SELECT语句中的数字的SALARY列。  
  336. 在前面的结果中,在输出中的每一行相对应于JOB_HISTORY表的一条记录,包括SALARY列值为0的列。  
  337.   
  338.   
  339.   
  340. [b]控制行顺序[/b]  
  341.      
  342.     用两个UNION运算产生一个英语句子  
  343.   
  344. COLUMN a_dummy NOPRINT  
  345. SELECT 'sing' AS "My dream", 3 a_dummy  
  346. FROM dual  
  347. UNION  
  348. SELECT 'I''d like to teach', 1  
  349. FROM dual  
  350. UNION   
  351. SELECT 'the world to', 2  
  352. FROM dual  
  353. ORDER BY 2;  
  354.   
  355. ORDER BY 只能用列、别名或第一个查询的列位置。  
  356.   
  357. 控制行顺序  
  358.   在默认情况下,输出以第一列的升序排序,你可以用ORDER BY子句来改变顺序。  
  359.   
  360. 使用ORDER BY来改变行的顺序  
  361.   ORDER BY子句在复合查询中只能用一次。如果使用了,ORDER BY子句必须放在最后面的查询中。ORDER BY子句接受列名、别名或位置记号。如果没有ORDER BY子句,幻灯片中的代码例子将按第一列的字母顺序产生下面的输出:  
  362.             My dream  
  363. i'd like to teach  
  364. sing  
  365. the world to  
  366.         /././././  
  367.   注:考虑一个多次使用UNION SET运算的复合查询,在这种情况下,ORDER BY子句中只能用位置而不能显式表示。在幻灯片的例子中3个SELECT列表的第二个位置分别是3、1、2。另外,因为输出按照第一个SELECT列表,所以别名My dream定义在第一行;指示第二列不输出的a_dummy也在第一列。
0 0
原创粉丝点击