多表查詢有如下幾種:
合并結(jié)果集;UNION、UNION ALL
連接查詢
內(nèi)連接[INNER] JOINON
外連接OUTER JOIN ON
左外連接LEFT [OUTER] JOIN
右外連接RIGHT [OUTER] JOIN
全外連接(MySQL不支持)FULL JOIN
自然連接NATURAL JOIN
子查詢
合并結(jié)果集
1.作用:合并結(jié)果集就是把兩個(gè)select語句的查詢結(jié)果合并到一起!
2.合并結(jié)果集有兩種方式:
UNION:去除重復(fù)記錄,例如:SELECT
?FROM t1 UNION SELECT * FROM t2;
UNION ALL:不去除重復(fù)記錄,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。


要求:被合并的兩個(gè)結(jié)果:列數(shù)、列類型必須相同。
連接查詢
連接查詢就是求出多個(gè)表的乘積,例如t1連接t2,那么查詢出的結(jié)果就是t1*t2。
?

連接查詢會(huì)產(chǎn)生笛卡爾積,假設(shè)集合A={a,b},集合B={0,1,2},則兩個(gè)集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以擴(kuò)展到多個(gè)集合的情況。
那么多表查詢產(chǎn)生這樣的結(jié)果并不是我們想要的,那么怎么去除重復(fù)的,不想要的記錄呢,當(dāng)然是通過條件過濾。通常要查詢的多個(gè)表之間都存在關(guān)聯(lián)關(guān)系,那么就通過關(guān)聯(lián)關(guān)系去除笛卡爾積。
你能想像到emp和dept表連接查詢的結(jié)果么?emp一共14行記錄,dept表一共4行記錄,那么連接后查詢出的結(jié)果是56行記錄。
也就你只是想在查詢emp表的同時(shí),把每個(gè)員工的所在部門信息顯示出來,那么就需要使用主外鍵來去除無用信息了。


使用主外鍵關(guān)系做為條件來去除無用信息
SELECT * FROM emp,dept WHEREemp.deptno=dept.deptno[q1];
在多表查詢中,在使用列時(shí)必須指定列所從屬的表,例如emp.deptno表示emp表的deptno列。

SELECT
emp.ename,emp.sal,emp.comm,dept.dname
FROM emp,dept
WHERE emp.deptno=dept.deptno;

還可以為表指定別名,然后在引用列時(shí)使用別名即可。
SELECT e.ename,e.sal,e.comm,d.dname
FROM
emp AS e,dept AS d
WHERE
e.deptno=d.deptno;[q1]
其中AS是可以省略的
內(nèi)連接
上面的連接語句就是內(nèi)連接,但它不是SQL標(biāo)準(zhǔn)中的查詢方式,可以理解為方言!SQL標(biāo)準(zhǔn)的內(nèi)連接為:
SELECT *
FROM emp e
內(nèi)連接的特點(diǎn):查詢結(jié)果必須滿足條件。例如我們向emp表中插入一條記錄:
其中deptno為50,而在dept表中只有10、20、30、40部門,那么上面的查詢結(jié)果中就不會(huì)出現(xiàn)“張三”這條記錄,因?yàn)樗荒軡M足e.deptno=d.deptno這個(gè)條件。
2.2外連接(左連接、右連接)
外連接的特點(diǎn):查詢出的結(jié)果存在不滿足條件的可能。
左連接:
SELECT * FROM emp e
LEFT OUTER[q3]JOIN dept d
ON e.deptno=d.deptno;
左連接是先查詢出左表(即以左表為主),然后查詢右表,右表中滿足條件的顯示出來,不滿足條件的顯示NULL。
這么說你可能不太明白,我們還是用上面的例子來說明。其中emp表中“張三”這條記錄中,部門編號(hào)為50,而dept表中不存在部門編號(hào)為50的記錄,所以“張三”這條記錄,不能滿足e.deptno=d.deptno這條件。但在左連接中,因?yàn)閑mp表是左表,所以左表中的記錄都會(huì)查詢出來,即“張三”這條記錄也會(huì)查出,但相應(yīng)的右表部分顯示NULL。
INNER可以省略,MySQL默認(rèn)的連接方式就是內(nèi)連接
不使用WHERE,而是使用ON
OUTER可以省略

右連接
右連接就是先把右表中所有記錄都查詢出來,然后左表滿足條件的顯示,不滿足顯示NULL。例如在dept表中的40部門并不存在員工,但在右連接中,如果dept表為右表,那么還是會(huì)查出40部門,但相應(yīng)的員工信息為NULL。
SELECT * FROM emp e
RIGHT OUTER JOIN dept d
ON e.deptno=d.deptno;

自然連接
大家也都知道,連接查詢會(huì)產(chǎn)生無用笛卡爾積,我們通常使用主外鍵關(guān)系等式來去除它。而自然連接無需你去給出主外鍵等式,它會(huì)自動(dòng)找到這一等式:
l兩張連接的表中名稱和類型完全一致的列作為條件,例如emp和dept表都存在deptno列,并且類型一致,所以會(huì)被自然連接找到!
當(dāng)然自然連接還有其他的查找條件的方式,但其他方式都可能存在問題!
SELECT * FROM emp NATURAL JOIN dept;
SELECT * FROM emp NATURAL LEFT JOIN dept;
SELECT * FROM emp NATURAL RIGHT JOIN
dept;
子查詢
一個(gè)select語句中包含另一個(gè)完整的select語句。
子查詢就是嵌套查詢,即SELECT中包含SELECT,如果一條語句中存在兩個(gè),或兩個(gè)以上SELECT,那么就是子查詢語句了。
子查詢出現(xiàn)的位置:
where后,作為條為被查詢的一條件的一部分;
from后,作表;
當(dāng)子查詢出現(xiàn)在where后作為條件時(shí),還可以使用如下關(guān)鍵字:
any
all
子查詢結(jié)果集的形式:
單行單列(用于條件)
單行多列(用于條件)
多行單列(用于條件)
多行多列(用于表)
練習(xí):
1.工資高于JONES的員工。
分析:
查詢條件:工資>JONES工資,其中JONES工資需要一條子查詢。
第一步:查詢JONES的工資
SELECT sal FROM emp WHERE ename='JONES'
第二步:查詢高于甘寧工資的員工
SELECT * FROM emp WHERE sal > (${第一步})
結(jié)果:
SELECT * FROM emp WHERE sal > (SELECT
sal FROM emp WHERE ename='JONES')
2、查詢與SCOTT同一個(gè)部門的員工。
l子查詢作為條件
l子查詢形式為單行單列
3、工資高于30號(hào)部門所有人的員工信息
分析:
SELECT * FROM
emp WHERE sal>(
SELECT MAX(sal)
FROM emp WHERE deptno=30);
查詢條件:工資高于30部門所有人工資,其中30部門所有人工資是子查詢。高于所有需要使用all關(guān)鍵字。
第一步:查詢30部門所有人工資
SELECT sal FROM emp WHERE deptno=30;
第二步:查詢高于30部門所有人工資的員工信息
SELECT * FROM emp WHERE sal > ALL (${第一步})
結(jié)果:
SELECT * FROM emp WHERE sal >ALL[q1](SELECT sal FROM emp
WHERE deptno=30)
l子查詢作為條件
l子查詢形式為多行單列(當(dāng)子查詢結(jié)果集形式為多行單列時(shí)可以使用ALL或ANY關(guān)鍵字)
4、查詢工作和工資與MARTIN(馬?。┩耆嗤膯T工信息
分析:
查詢條件:工作和工資與MARTIN完全相同,這是子查詢
第一步:查詢出MARTIN的工作和工資
SELECT job,sal FROM emp WHERE
ename='MARTIN'
第二步:查詢出與MARTIN工作和工資相同的人
SELECT * FROM emp WHERE (job,sal) IN (${第一步})
結(jié)果:
SELECT * FROM emp WHERE (job,sal) IN
(SELECT job,sal FROM emp WHERE ename='MARTIN')
5、有2個(gè)以上直接下屬的員工信息
SELECT * FROM
emp WHERE empno IN(
SELECT mgr FROM
emp GROUP BY mgr HAVING COUNT(mgr)>=2);
l子查詢作為條件
l子查詢形式為單行多列
5、查詢員工編號(hào)為7788的員工名稱、員工工資、部門名稱、部門地址
分析:(無需子查詢)
查詢列:員工名稱、員工工資、部門名稱、部門地址
查詢表:emp和dept,分析得出,不需要外連接(外連接的特性:某一行(或某些行)記錄上會(huì)出現(xiàn)一半有值,一半為NULL值)
條件:員工編號(hào)為7788
第一步:去除多表,只查一張表,這里去除部門表,只查員工表
SELECT ename, sal FROM emp e WHERE empno=7788
第二步:讓第一步與dept做內(nèi)連接查詢,添加主外鍵條件去除無用笛卡爾積
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, dept d
WHERE e.deptno=d.deptno AND empno=7788
第二步中的dept表表示所有行所有列的一張完整的表,這里可以把dept替換成所有行,但只有dname和loc列的表,這需要子查詢。
第三步:查詢dept表中dname和loc兩列,因?yàn)閐eptno會(huì)被作為條件,用來去除無用笛卡爾積,所以需要查詢它。
SELECT dname,loc,deptno FROM dept;
第四步:替換第二步中的dept
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, (SELECT dname,loc,deptno FROM
dept) d
WHERE e.deptno=d.deptno AND e.empno=7788
子查詢作為表
l子查詢形式為多行多列
6、自連接:自己連接自己,起別名
求7369員工編號(hào)、姓名、經(jīng)理編號(hào)和經(jīng)理姓名
SELECT e1.empno , e1.ename,e2.mgr,e2.ename
FROMemp e1, emp e2
WHEREe1.mgr = e2.empno AND e1.empno = 7369;
練習(xí):
求各個(gè)部門薪水最高的員工所有信息
select e.* from emp e,
--部門最高工資
(select max(sal) maxsal,deptno from emp
group by deptno) a
where e.deptno = a.deptno
and e.sal =a.maxsal