6多表查询
<h3>多表查询基本语法:</h3>
<ul>
<li>笛卡尔积,结果的行数是两个表的行数的积,联合查询性能低
<code>SELECT * FROM emp,dept;</code></li>
<li>消除笛卡尔积,利用外键的关系来消除,等值连接的方式消除笛卡尔积
<code>SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;</code></li>
</ul>
<h3>多表查询实例</h3>
<pre><code>SELECT a.empno 雇员编号,a.ename 雇员姓名,a.job 职位,a.sal 基本工资,b.dname 部门名称,b.loc 部门位置 FROM emp a,dept b WHERE a.deptno=b.deptno;
SELECT * FROM salgrade ;--要求查询员工信息,工资等级,联合查询的条码是很灵活的
SELECT e.empno,e.ename,e.hiredate,e.sal,s.grade,s.losal,s.hisal FROM emp e,salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal; </code></pre>
<ul>
<li>对工资等级的显示人性化
<pre><code>SELECT e.empno,e.ename,e.hiredate,e.sal,decode(s.grade,'1','E级',2,'D级',3,'C级','4','B级','5','A级') salgrade FROM emp e,salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal </code></pre></li>
<li>三表查询,不成文规定:消除笛卡尔积的条码个数=表的张数-1
<pre><code>SELECT e.ename,e.job,e.sal,d.dname,s.grade,decode(s.grade,'1','E级',2,'D级',3,'C级','4','B级','5','A级') grade_1 FROM emp e,dept d,salgrade s WHERE e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal ;</code></pre></li>
</ul>
<h3>表的连接操作,两表中没有相等的数据,数据丢失问题</h3>
<ul>
<li>插入额外的数据
<pre><code>INSERT INTO emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (8888,'李兴华','CLERK',7369,SYSDATE,800,100,NULL);
SELECT * from emp,dept WHERE emp.deptno = dept.deptno ;</code></pre></li>
<li>左连接与右连接用+号实现</li>
<li>左连接
<code>SELECT e.empno,e.ename,e.job,d.deptno,d.dname,d.loc FROM emp e,dept d WHERE e.deptno = d.deptno(+);</code></li>
<li>右连接
<code>SELECT * FROM emp e,dept d WHERE e.deptno(+) = d.deptno ;</code></li>
</ul>
<h3>自身关联</h3>
<ul>
<li>emp表自身关联,查找雇员工号,雇员名字,上司编号,上司名字
<pre><code>SELECT emp.empno,emp.ename,memp.empno,memp.ename FROM emp,emp memp WHERE emp.mgr=memp.empno ;
SELECT emp.empno,emp.ename,memp.empno,memp.ename FROM emp,emp memp WHERE emp.mgr=memp.empno(+);</code></pre></li>
<li>复杂示例:查询在1981年雇佣的全部雇员编号、姓名、雇用日期(按年-月-日显示)、工作、领导姓名、雇员月工资、雇员年工资(基本工资+奖金),雇员工资等级、部门编号、部门名称、部门位置,
--并且要求这些雇员的月基本工资在1500~3500元之间,将最后的结果按照年工资的降序排列,如果年工资相等,则按照工作时间进行排序。
<pre><code>SELECT e.empno,e.ename,to_char(e.hiredate,'yyyy-mm-dd'),e.job,me.ename,e.sal,NVL2(e.comm,e.sal+e.comm,e.sal)*12 yearsal,s.grade,d.deptno,d.dname,d.loc FROM emp e,emp me,salgrade s,dept d WHERE e.mgr=me.empno(+) AND e.deptno=d.deptno(+) AND (e.sal BETWEEN s.losal AND s.hisal) AND (e.sal BETWEEN 1500 AND 3500) AND to_char(e.hiredate,'yyyy')=1981 ORDER BY yearsal DESC,e.hiredate ASC;</code></pre></li>
</ul>
<h3>SQL:1999语法</h3>
<pre><code>SELECT * FROM emp CROSS JOIN dept ;--交叉连接,相当于笛卡尔积
SELECT * FROM emp NATURAL JOIN dept ;--自然连接,有共同字段的记录能连接,不能连接的叫悬浮元组。
SELECT * FROM emp JOIN dept USING(deptno) ;--USING子句指定连接的字段,可以去除重复列
SELECT * FROM emp e JOIN salgrade s ON (e.sal BETWEEN s.losal AND s.hisal) ;--使用on子句指定关系</code></pre>
<h3>外连接:左外连接、右外连接、全连接,前面用的(+)号只能是oracle用</h3>
<pre><code>SELECT * FROM emp e LEFT OUTER JOIN dept d ON e.deptno=d.deptno ;--左外连接
SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno=d.deptno ;--右外连接
SELECT * FROM emp e FULL OUTER JOIN dept d ON e.deptno=d.deptno ;--全外连接</code></pre>
<h3>数据的集合运算,二目运算符:并、差、交、笛卡尔积</h3>
<pre><code>/*
union(并集):返回查询的结果,去除重复项。
union all(并集):重复项也重复显示。
minus(差集):返回查询结果中不同的部分。
intersect(交集):返回结果中相同的部分。
*/</code></pre>
<h4>并集操作</h4>
<pre><code>SELECT * FROM dept --union重复内容只显示一次
UNION
SELECT * FROM dept WHERE deptno=10;
--union all重复内容不过滤
SELECT * FROM dept
UNION ALL
SELECT * FROM dept WHERE deptno=10;
--使用or
SELECT * FROM emp WHERE job='SALESMAN' OR job='CLERK';--0.031秒
--使用union。使用union、union all能达到or相同的目的,但是使用union、union all的性能更好
SELECT * FROM emp WHERE job='SALESMAN'
UNION
SELECT * FROM emp WHERE job='CLERK';</code></pre>
<h4>差集操作:显示不重叠部分</h4>
<pre><code>SELECT * FROM dept
MINUS
SELECT * FROM dept WHERE deptno=10;</code></pre>
<h4>交集操作:只显示重叠部分</h4>
<pre><code>SELECT * FROM dept
INTERSECT
SELECT * FROM dept WHERE deptno=10;</code></pre>
<h4>5种连接</h4>
<ul>
<li>自然连接natural join 不用联接条件、重复的列自动去掉</li>
<li>内连接inner join(join) 要联接条件、重复的列不去掉</li>
<li>外连接outer join ,分三种left join 、right join 右联接、full join ,即不满足条码的行也可以返回</li>
<li>交叉连接cross join ,不带on,只能根据两表的条件减数据,返回笛卡尔积</li>
<li>自连接,同一张表多连接</li>
</ul>
<p><a href="https://www.cnblogs.com/wishyouhappy/p/3678852.html">5种基本类型的连接</a></p>
<h3>总结</h3>
<ul>
<li>数据表连接的方式有:自身连接、外连接、内连接</li>
<li>多表连接有oracle特有的连接方法和SQL:1999语法标准两种</li>
</ul>