6.MySql中的SQL語句(五):多表查詢

多表查詢有如下幾種:

合并結(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列。


上面查詢結(jié)果會(huì)把兩張表的所有列都查詢出來,也許你不需要那么多列,這時(shí)就可以指定要查詢的列了。


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

INNER[q1]JOIN dept d

ON[q2]e.deptno=d.deptno;

內(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容