關係查詢(Oracle)
什麼叫子查詢?
子查詢也叫巢狀查詢,是指嵌入在其他sql語句中的select語句。
單行子查詢
單行子查詢是指只返回一條記錄的子查詢語句。
查詢工資最高的人的資訊
select * from emp where sal = (select max(sal) from emp);
顯示部門平均工資低於2000的部門的員工資訊
select * from emp where deptno in (select deptno from emp group by deptno having avg(sal)<2000);
多行子查詢
多行子查詢是指返回多行資料的子查詢。
查詢和部門10 工作相同的僱員的名字,崗位,工資,部門號
- 先查詢部門10有哪些崗位。
select distinct(job) from emp where deptno=10;
- 顯示這些崗位的員工
select * from emp where job in (select distinct(job) from emp where deptno=10);
在子查詢中使用all操作符 [熟悉]
顯示工資比部門30所有員工的工資都高的員工姓名 【要大於所有】
select * from emp where sal > all(select sal from emp where deptno=30);
在子查詢中使用any操作符 [熟悉]
顯示工資比部門30任意員工的工資都高的員工姓名 【只要大於一個】
select * from emp where sal > any(select sal from emp where deptno=30);
多列子查詢
查詢和SCOTT部門和崗位完全相同的所有僱員。
思路1:
使用兩個子查詢分別查詢
select * from emp where deptno = (select deptno from emp where ename='SCOTT') and job = (select job from emp where ename='SCOTT');
思路2:
使用括號 oracle特有的,其他資料庫不一定支援。
select * from emp where (deptno,job)= (select deptno,job from emp where ename='SCOTT');
使用子查詢建立新表
寫法:create 新表名 as select from 舊錶名
create table empbak as select * from emp where 1=0;--建立空表
create table empbak2(id,name,sal) as select empno,ename,sal from emp;--建立有內容表
使用子查詢自我複製資料
寫法:insert into 新表名[列名] select [*,列名] from舊錶。
insert into empbak(empno,ename,job,mgr,hiredate,sal,comm,deptno) select * from emp;
insert into empbak(empno,ename) select * from emp;--錯誤寫法,值過多
insert into empbak(empno,ename) select empno,ename from emp;
合併查詢
union 用於取得兩個結果集的並集,自動去掉重複的行。
select * from emp union select * from emp;--14條記錄
union all 將兩個結果集相加,不會去掉重複的行
select * from emp union all select * from emp;--28條記錄
intersect 取交集,自動去掉重複的行。
select * from emp where sal>800 intersect select * from emp where sal>2000;
minus 取差集,自動去掉重複的行。
select * from emp where sal>800 minus select * from emp where sal>2000;
--不同表 取出相同型別的列 也可以使用 建議使用別名
select empno idno,ename idname from emp union select deptno idno,dname idname from dept;
select empno ,ename from emp union select deptno ,dname from dept;
笛卡爾集 交叉連線 【熟悉cross join】
在多表查詢的時候,如果不帶任何條件,則會出現笛卡爾集。
select * from emp;--14條記錄
select * from dept;--4條記錄
select * from emp,dept;--56條記錄 隱式交叉連線
select * from emp cross join dept;--顯示交叉連線
select * from salgrade;--5條記錄
select * from dept,emp,salgrade;--280條記錄
select * from dept cross join emp cross join salgrade;
笛卡爾集出現原理:
從dept中取出一條記錄,分別於emp中的每一條記錄匹配。
直到dept中的所有記錄於emp中的所有記錄全部匹配。
怎樣避免笛卡爾集?
多表查詢的條件至少不能少於表的個數-1.
等值連線
一個使用者查詢請求涉及到多個表的時候,連線多個表的條件為=時,就是等值連線查詢。
在實際開發中,我們不可避免的需要對兩張或是兩張以上的表進行聯合查詢,比如顯示僱員名字,僱員工資以及所在部門的名字。
--普通寫法
select emp.ename,emp.sal,dept.dname from dept ,emp where dept.deptno = emp.deptno;
--正確寫法 【不建議】
select ename,sal,dname from dept ,emp where dept.deptno = emp.deptno;
--錯誤寫法,未明確定義列
select ename,sal,dname,deptno from dept ,emp where dept.deptno = emp.deptno;
--使用別名 [推薦寫法]
select t2.ename,t2.sal,t1.dname from dept t1,emp t2 where t1.deptno = t2.deptno;
顯示部門號為10的部門名,員工名和工資
select t1.ename,t1.sal,t2.dname from emp t1, dept t2 where t1.deptno=t2.deptno and t1.deptno=10;
非等值連線
一個使用者查詢請求涉及到多個表的時候,連線多個表的條件不是=時,就是非等值連線查詢;
查詢工資級別為1的員工資訊。
select * from emp t1,salgrade t2 where t2.grade=1 and t1.sal between t2.losal and t2.hisal;
顯示各個員工的姓名,工資以及工資級別。
select emp.ename,emp.sal,salgrade.grade from emp,salgrade where emp.sal between salgrade.losal and salgrade.hisal;
自然連線 【熟悉】
自然連線是通過對參與表關係中所有同名的屬性對取等(即相等比較)來完成的,故無須自己新增連線條件
select * from emp natural join dept;--有同名列場景
select * from emp,dept where emp.deptno = dept.deptno;--效果等價
select * from emp natural join salgrade;--如果沒有同名列 生成笛卡爾集
using連線 【熟悉】
相比較natural 更加靈活,可以指定多個列。
需要使用() ()內可以有多個列,但必須是兩者都有的列,使用逗號分隔。
select * from emp join dept using (deptno);
select * from emp,dept where emp.deptno = dept.deptno;--效果等價
on連線 【熟悉】
相比較using更加靈活,可以指定不同列名。
select * from emp join dept on emp.deptno = dept.deptno;
自連線
顯示員工JONES的上級領導的姓名
select * from emp where empno = ( select mgr from emp where ename = 'JONES');
顯示所有員工和他上級的姓名?
思路 把emp看成兩張表。(worker,manager)
select worker.ename,manager.ename from emp worker,emp manager where worker.mgr = manager.empno;
疑惑?
只顯示了13條記錄,KING沒有顯示,因為他沒有上級。
Oracle的連線分類【瞭解】
oracle的連線分為內連線和外連線。
什麼叫內連線?
內連線實際上就是利用where子句對兩張表形成的笛卡爾集進行篩選。是開發中用的最多的連線查詢,前面部分我們學習的都是內連線。
基本語法:
select 列名1,…… from 表1 inner join 表2 on 查詢條件;
效果等同於select 列名1,…… from 表1,表2 where 查詢條件;
外連線
外連線分成左外聯,右外聯,完全外聯。
外連線 左連線
如果左表的記錄不能和右表記錄進行關聯也要展示。
場景:有學生5名,其中3名學生缺席考試。
create table stu(id number,name varchar2(20));
create table exam(id number,grade number);
insert into stu values(1,'小明');
insert into stu values(2,'張三');
insert into stu values(3,'李四');
insert into stu values(4,'王五');
insert into stu values(5,'趙六');
insert into exam values(1,90);
insert into exam values(2,100);
select * from stu,exam where stu.id = exam.id;--沒有參加考試的學生將不能顯示
select * from stu left join exam on stu.id = exam.id;--沒有參加考試的學生可以顯示
select * from stu,exam where stu.id = exam.id(+);--另外的寫法
外連線 右連線
如果右表的記錄不能和左表關聯也要展示
場景:有插班生進行考試,插班生id在學生資訊表中沒有。
insert into exam values(12,100);
select * from stu right join exam on stu.id = exam.id; --顯示插班生考試成績
select * from stu,exam where stu.id(+) = exam.id;--另一種寫法
select * from exam left join stu on stu.id = exam.id;--此種寫法跟表名順序相關,左右連互轉
select * from stu,exam where exam.id = stu.id(+);--此種寫法與表名的順序無關,跟欄位相關
外連線 完全外聯
不管是否有匹配記錄,都顯示出來。
select * from stu full outer join exam on stu.id = exam.id;
select * from stu full join exam on stu.id = exam.id;
三表連線
查詢員工的員工資訊,部門名稱,工資級別
select t1.*,t2.dname,t3.grade from emp t1,dept t2,salgrade t3
where t1.deptno = t2.deptno
and t1.sal between t3.losal and t3.hisal;