MySQL加強(二)——高級查詢

1.分組查詢


1.1什么是分組:

針對于班上所有的同學(xué):

分組情況1-按照性別分組:男生一組痕支,女生一組颁虐,之后可以統(tǒng)計男生和女生的數(shù)量;

分組情況2-按照年齡段分組:80后一組卧须,90后一組另绩;

分組情況3-按照籍貫分組:廣東一組,湖南一組花嘶,江西一組笋籽;

1.2語法:

SELECT [DISTINCT] *|分組字段1 [別名] [,分組字段2 [別名] ,…] | 統(tǒng)計函數(shù)

FROM 表名稱 [別名], [表名稱 [別名] ,…]

[WHERE 條件(s)]

[GROUP BY 分組字段1 [,分組字段2 ,…]]

[ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC]];

注意:

  • 使用GROUP BY子句將表分成小組
  • 組函數(shù)忽略空值,可以使用ifnull
  • 結(jié)果集隱式按升序排列,如果需要改變排序方式可以使用order by 子句

1.3練習(xí):

-- 1,按照職位分組椭员,求出每個職位的最高和最低工資
SELECT MAX(SAL),JOB FROM emp GROUP BY JOB;

-- 2车海,查詢出每一個部門員工的平均工資
SELECT AVG(SAL),DEPTNO FROM emp GROUP BY DEPTNO;

-- 3,查詢平均工資高于2000的部門和其平均工資
SELECT AVG(SAL),DEPTNO FROM emp GROUP BY DEPTNO HAVING AVG(SAL) >=2000;

-- 4隘击,查詢各個部門和崗位的平均工資
SELECT AVG(SAL),DEPTNO,JOB FROM emp GROUP BY DEPTNO,JOB;

-- 5侍芝,查詢各個管理人員下員工的平均工資,其中最低工資不能低于1300埋同,不計算老板
SELECT AVG(SAL),DEPTNO,JOB FROM emp GROUP BY job HAVING AVG(SAL) >1300;

-- 6州叠,查詢在80,81,82,83年各進公司多少人
SELECT COUNT(*),YEAR(HIREDATE) FROM emp WHERE YEAR(HIREDATE) IN ('1980','1981','1982','1983') GROUP BY YEAR(HIREDATE);

1.4分組函數(shù)使用注意:

  • 1,出現(xiàn)在SELECT列表中的字段莺禁,如果出現(xiàn)的位置不是在分組函數(shù)中留量,那么必須出現(xiàn)在GROUP BY子句中

  • 2,在GROUP BY 子句中出現(xiàn)的字段哟冬,可以不出現(xiàn)在SELECT列表中

  • 3楼熄,如果沒有GROUP BY子句,SELECT列表中的任何列或表達式不能使用統(tǒng)計函數(shù)(單獨使用統(tǒng)計函數(shù)除外):

分組函數(shù)單獨使用:

SELECT COUNT(empno) FROM emp;

錯誤的使用,出現(xiàn)了其他字段:

SELECT empno,COUNT(empno) FROM emp;

正確做法:

SELECT empno,COUNT(empno) FROM emp GROUP  BY empno,job;

如果現(xiàn)在要進行分組的話浩峡,則SELECT子句之后可岂,只能出現(xiàn)分組的字段和統(tǒng)計函數(shù),其他的字段不能出現(xiàn):

正確做法:

SELECT job,COUNT(empno),AVG(sal)

FROM emp

GROUP BY job;

錯誤的做法:

SELECT deptno,job,COUNT(empno),AVG(sal)

FROM emp

GROUP BY job;

正確做法:

SELECT deptno,job,COUNT(empno),AVG(sal)

FROM emp

GROUP BY  deptno,job;

在group by 子句中翰灾,可以按單列進行分組缕粹,也可以在多列上進行分組稚茅,多列分組就是按照多個字段的組合進行分組,最終的結(jié)果也會按照分組字段進行排序顯示平斩。

1.5分組函數(shù)執(zhí)行流程

查詢在80,81,82,83年各進公司多少人

SELECT COUNT(empno), YEAR(hiredate) FROM emp WHERE YEAR(hiredate) IN ('1980','1981','1982','1983') GROUP BY YEAR(hiredate)

在整個語句執(zhí)行的過程中亚享,最先執(zhí)行的是WHERE子句,在對表數(shù)據(jù)進行過濾后绘面,符合條件的數(shù)據(jù)通過Group by進行分組欺税,分組數(shù)據(jù)通過Having子句進行組函數(shù)過濾,最終的結(jié)果通過order by子句進行排序揭璃,排序的結(jié)果被返回給用戶晚凿。

注意點:WHERE和HAVING的區(qū)別
WHERE:是在執(zhí)行GROUP BY操作之前進行的過濾,表示從全部數(shù)據(jù)之中篩選出部分的數(shù)據(jù)瘦馍,在WHERE之中不能使用統(tǒng)計函數(shù)歼秽;
HAVING:是在GROUP BY分組之后的再次過濾,可以在HAVING子句中使用統(tǒng)計函數(shù)情组;

image.png

2.多表查詢


2.1笛卡爾積:

沒有連接條件的表關(guān)系返回的結(jié)果燥筷。

多表查詢會產(chǎn)生笛卡爾積:
假設(shè)集合A={a,b},集合B={0,1,2}呻惕,則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}荆责。

實際運行環(huán)境下,應(yīng)避免使用全笛卡爾集亚脆。

select * from emp,dept
image.png

解決方案: 在WHERE加入有效的連接條件---->等值連接/不等值連接
注意:連接 n張表,至少需要 n-1個連接條件做院。

image.png

2.2隱式連接

沒有join,通過Where的條件進行連接

2.2.1語法
SELECT [DISTINCT] * | 字段 [別名] [,字段 [別名] ,…]
FROM 表名稱 [別名], [表名稱 [別名] ,…]
[WHERE 條件(S)]
[ORDER BY 排序字段 [ASC|DESC] [,排序字段 [ASC|DESC] ,…]];
2.2.2隱式等值連接

使用表連接從多個表中查詢數(shù)據(jù)

SELECT  table1.column, table2.column
FROM        table1, table2
WHERE   table1.column1 = table2.column2;

在 WHERE 子句中寫入連接條件

當(dāng)多個表中有重名列時濒持,必須在列的名字前加上表名作為前綴

等值連接是連接操作中最常見的一種键耕,通常是在存在主外鍵約束條件的多表上建立的,連接條件中的兩個字段通過等號建立等值關(guān)系柑营。

需求:查詢員工編號屈雄,員工名稱,員工所屬部門的編號和名稱.

2.2.3使用別名

使用表的別名簡化了查詢官套,提高了查詢的性能

SELECT e.empno,e.ename,d.deptno,d.dname FROM emp e,dept d WHERE e.deptno = d.deptno;
2.2.4對多表做等值連接

為了連接n個表酒奶,至少需要n-1個連接條件。例如奶赔,為了連接三個表惋嚎,至少需要兩個連接條件

2.2.5非等值連接

查詢員工的姓名,工資,所在部門的名稱,以及工資的等級.
輸出:

SELECT  e.ename, e.sal,d.dname,s.grade FROM emp e,dept d,salgrade s WHERE e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal

2.3顯示連接

隱式連接的問題在于:
1,需要在where條件中寫連接條件站刑,如果忘記寫另伍,代碼不會出錯,產(chǎn)生笛卡爾乘積绞旅;
2摆尝,隱式連接只能做內(nèi)連接温艇;

image.png
2.3.1內(nèi)連接
SELECT  table1.column, table2.column
FROM    table1 JOIN table2  ON(table1.column_name = table2.column_name)
  • 自然連接的條件是基于表中所有同名列的等值連接

  • 為了設(shè)置任意的連接條件或者指定連接的列,需要使用ON子句

  • 連接條件與其它的查詢條件分開書寫

  • 使用ON 子句使查詢語句更容易理解

  • 先執(zhí)行join再執(zhí)行過濾

  • 如果要先過濾再join堕汞,那么在join中可以通過join on ..and ..and來先過濾再連接

練習(xí)勺爱,使用顯式內(nèi)連接查詢:
需求:查詢員工編號,員工名稱臼朗,員工所屬部門的編號和名稱.

SELECT e.empno,e.ename,d.deptno,d.dname  FROM emp e JOIN dept d ON  e.deptno = d.deptno

SELECT e.empno,e.ename,d.deptno,d.dname  FROM emp e JOIN dept d  USING(deptno)
2.3.2外連接

需求:查詢出至少有一個員工的所有部門編號邻寿、名稱,并統(tǒng)計出這些部門的平均工資视哑、最低工資、最高工資誊涯。
需求:查詢每一個部門的總?cè)藬?shù).

deptno dname COUNT(empno)
10 ACCOUNTING 3
20 RESEARCH 5
30 SALES 6
40 OPERATIONS 0

外連接查詢:

左外連接:查詢出JOIN左邊表的全部數(shù)據(jù)查詢出來,JOIN右邊的表不匹配的數(shù)據(jù)使用NULL來填充數(shù)據(jù).
右外連接:查詢出JOIN右邊表的全部數(shù)據(jù)查詢出來,JOIN左邊的表不匹配的數(shù)據(jù)使用NULL來填充數(shù)據(jù).

SELECT dname,COUNT(empno) FROM emp JOIN dept USING (deptno) GROUP BY deptno;

SELECT deptno,dname,COUNT(empno) FROM emp RIGHT JOIN dept USING (deptno) GROUP BY deptno,deptno;

左外連接
在LEFT OUTER JOIN中挡毅,會返回所有左邊表中的行,即使在右邊的表中沒有可對應(yīng)的列值暴构。即對連接中左邊的表中的記錄不加限制

SELECT  table1.column, table2.column
FROM    table1 LEFT [OUTER] JOIN table2 ON (table1.column_name = table2.column_name);

右邊外連接
RIGHT OUTER JOIN中會返回所有右邊表中的行跪呈,即使在左邊的表中沒有可對應(yīng)的列值。即對連接中右邊的表中的記錄不加限制

SELECT  table1.column, table2.column
FROM    table1 RIGHT [OUTER] JOIN table2 ON (table1.column_name = table2.column_name);

全外連接
FULL OUTER JOIN中會返回所有右邊表中的行和所有左邊表中的行取逾,即使在左邊的表中沒有可對應(yīng)的列值或者右邊的表中沒有可對應(yīng)的列

SELECT  table1.column, table2.column
FROM    table1 FULL [OUTER] JOIN table2 ON (table1.column_name = table2.column_name);

MYSQL中暫時不支持全連接,可以通過union +左右連接來完成耗绿;

2.3.3自連接

在查詢語句中,一張表可以重復(fù)使用多次砾隅,完成多次連接的需要误阻;

需求:查詢員工名稱和其對應(yīng)經(jīng)理的名稱.

SELECT e.empno,e.ename,m.ename FROM emp e LEFT JOIN emp m ON e.mgr = m.empno;

3.子查詢


3.1子查詢

子查詢指的就是在一個查詢之中嵌套了其他的若干查詢.
在使用select語句查詢數(shù)據(jù)時,有時候會遇到這樣的情況,在where查詢條件中的限制條件不是一個確定的值晴埂,而是一個來自于另一個查詢的結(jié)果究反。

子查詢一般出現(xiàn)在FROM和WHERE子句中.

SELECT  <select_list>
FROM table
WHERE   expr  operator
            (SELECT select_list
             FROM   table);
  • 1、子查詢在主查詢前執(zhí)行一次
  • 2儒洛、主查詢使用子查詢的結(jié)果

練習(xí)
1精耐、查詢大于公司平均工資的員工姓名

SELECT ename,sal FROM emp WHERE sal >
    (SELECT AVG(sal) FROM emp)

2、查詢出工資比MARTIN還要高的全部雇員信息

SELECT * FROM emp WHERE sal >
    (SELECT sal FROM emp WHERE ename = 'MARTIN')

使用子查詢的注意事項:

  • 1琅锻、子查詢要用括號括起來
  • 2卦停、將子查詢放在比較運算符的右邊(增強可讀性)
  • 3、對單行子查詢使用單行運算符
  • 4恼蓬、對多行子查詢使用多行運算符

3.2子查詢種類

3.2.1單行單列子查詢:

只包含一個字段的查詢惊完,返回的查詢結(jié)果也只包含一行數(shù)據(jù)
1、返回一行記錄
2滚秩、使用單行記錄比較運算符:=专执;>;>=郁油;<本股;<=攀痊;<>

練習(xí):
1、查詢大于公司平均工資的員工姓名

SELECT ename,sal FROM emp WHERE sal >
    (SELECT AVG(sal) FROM emp)

2拄显、查詢出工資比MARTIN還要高的全部雇員信息

SELECT * FROM emp WHERE sal >
    (SELECT sal FROM emp WHERE ename = 'MARTIN')
3.2.2多行單列子查詢:

只包含了一個字段苟径,但返回的查詢結(jié)果可能多行或者零行(多行子查詢返回多行單列)
1、返回多行
2躬审、使用多行比較運算符
IN:與列表中的任意一個值相等 :需求:查詢工資等于部門經(jīng)理的員工信息.
ANY:與子查詢返回的任意一個值比較
1): = ANY:此時和IN操作符相同. :需求:查詢工資等于任意部門經(jīng)理的員工信息.
2): > ANY:大于子查詢中最小的數(shù)據(jù). :需求:查詢工資大于任意部門經(jīng)理的員工信息.
3): < ANY:大于子查詢中最大的數(shù)據(jù). :需求:查詢工資小于任意部門經(jīng)理的員工信息.
ALL:與子查詢返回的每一個值比較
1): > ALL:大于子查詢中最大的數(shù)據(jù).
2): < ALL:小于子查詢中最小的數(shù)據(jù).

練習(xí)
查詢平均工資高于公司平均工資的部門信息

SELECT deptno,AVG(sal) FROM  dept JOIN emp USING (deptno) GROUP BY deptno HAVING AVG(sal) > 
(
    SELECT AVG(sal) FROM emp
);


select * from departments where department_id in 
(select department_id from employees 
    group by department_id having avg(salary)>
        (select avg(salary) from employees));
3.2.3多列子查詢:

包含多個字段的返回棘街,查詢結(jié)構(gòu)可能是單行或者多行。(子查詢返回的結(jié)果是多行多列)

一般會把子查詢返回的結(jié)果當(dāng)成一個臨時表承边,接著在臨時表上繼續(xù)查詢或者連接查詢遭殉;
注意,多行多列的子查詢返回的結(jié)果必須要設(shè)置一個臨時表名博助;

查詢出每個部門的編號险污、名稱、部門人數(shù)富岳、平均工資:

SELECT d.deptno,d.dname,COUNT(e.empno),IFNULL(AVG(e.sal),0)
FROM dept d JOIN emp e USING (deptno)
GROUP BY d.deptno,d.dname

分析性能:笛卡爾積數(shù)量:

可以先把每一個部門的編號,總?cè)藬?shù),平均工資先查詢出來.

SELECT deptno dno,COUNT(empno) count ,AVG(sal) avg  FROM emp GROUP BY dno

再和dept表聯(lián)合查詢部門名稱.

SELECT  dept.deptno,temp.count,temp.avg  FROM dept JOIN (SELECT deptno dno,COUNT(empno) count ,AVG(sal) avg  FROM emp GROUP BY deptno) temp ON dept.deptno = temp.dno
image.png

3.3UNION/UNION ALL

JOIN是用于把表橫向連接蛔糯,UNION/UNION ALL是用于把表縱向連接(一般用于做查詢的臨時表)
UNION 操作符用于合并兩個或多個 SELECT 語句的結(jié)果集。

3.3.1注意

1窖式,UNION 內(nèi)部的 SELECT 語句必須擁有相同數(shù)量的列蚁飒。
2,列也必須擁有兼容的數(shù)據(jù)類型萝喘。
3淮逻,每條 SELECT 語句中的列的順序必須相同。
4蜒灰,UNION 結(jié)果集中的列名總是等于 UNION 中第一個 SELECT 語句中的列名
5弦蹂,UNION 操作符選取不同的值。如果允許重復(fù)的值强窖,請使用 UNION ALL(性能高).

3.3.2語法:
SELECT column_name(s) FROM table_name1
UNION|UNION ALL
SELECT column_name(s) FROM table_name2
3.3.3在MYSQL 中實現(xiàn)FULL JOIN:

查詢員工的編號,名稱和部門名稱.

1:先在emp表中插入一條數(shù)據(jù),并設(shè)置depto為NULL.
2:查詢

SELECT empno,ename,dname FROM emp LEFT JOIN dept USING (deptno)
UNION
SELECT empno,ename,dname FROM emp RIGHT JOIN dept USING (deptno)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凸椿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子翅溺,更是在濱河造成了極大的恐慌脑漫,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咙崎,死亡現(xiàn)場離奇詭異优幸,居然都是意外死亡,警方通過查閱死者的電腦和手機褪猛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門网杆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事碳却《又龋” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵昼浦,是天一觀的道長馍资。 經(jīng)常有香客問我,道長关噪,這世上最難降的妖魔是什么鸟蟹? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮使兔,結(jié)果婚禮上建钥,老公的妹妹穿的比我還像新娘。我一直安慰自己火诸,他們只是感情好锦针,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著置蜀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悉盆。 梳的紋絲不亂的頭發(fā)上盯荤,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音焕盟,去河邊找鬼秋秤。 笑死,一個胖子當(dāng)著我的面吹牛脚翘,可吹牛的內(nèi)容都是我干的灼卢。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼来农,長吁一口氣:“原來是場噩夢啊……” “哼鞋真!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起沃于,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤涩咖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后繁莹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體檩互,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年咨演,在試婚紗的時候發(fā)現(xiàn)自己被綠了闸昨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饵较,靈堂內(nèi)的尸體忽然破棺而出拍嵌,到底是詐尸還是另有隱情,我是刑警寧澤告抄,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布撰茎,位于F島的核電站,受9級特大地震影響打洼,放射性物質(zhì)發(fā)生泄漏龄糊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一募疮、第九天 我趴在偏房一處隱蔽的房頂上張望炫惩。 院中可真熱鬧,春花似錦阿浓、人聲如沸他嚷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筋蓖。三九已至,卻和暖如春退敦,著一層夾襖步出監(jiān)牢的瞬間粘咖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工侈百, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瓮下,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓钝域,卻偏偏與公主長得像讽坏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子例证,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容