學(xué)習(xí)目的
- 掌握Mysl常用的查詢語句
- 掌握數(shù)據(jù)查詢在實際開發(fā)中的應(yīng)用
一.Mysql數(shù)據(jù)查詢(DQL)
- DQL概念
DQL全稱Data Query Language性宏,意為數(shù)據(jù)查詢語言乾蛤。在數(shù)據(jù)庫學(xué)習(xí)中,最重要的就是查詢語句撤师,因為數(shù)據(jù)庫中的數(shù)據(jù)就是通過各種查詢操作展示給用戶。 - 特點
DQL最重要的語句是select語句。 - 語法格式
select 字段名1,字段名2,字段名3,.... from 表名; - 注意點
- 實際開發(fā)中不建議使用 select *玉控,效率較低(原因是在底層會將*號先轉(zhuǎn)換為所有字段再去查詢,不如直接寫出字段去查詢)狮惜;
- SQL語句中不區(qū)分大小寫(Windows系統(tǒng)中不區(qū)分高诺,但Linux中區(qū)分);
- 理清每一個查詢語句的執(zhí)行順序碾篡,通過分步查詢虱而,有利于理解查詢的執(zhí)行原理以及調(diào)試。
1.1 簡單查詢
查詢單個字段
select 字段名 from 表名;查詢多個字段
select 字段名1,字段名2,字段名3,.... from 表名;查詢某個字段 乘倍數(shù)之后的結(jié)果(字段可以參與數(shù)學(xué)運算)
select 字段名1,字段名2 *倍數(shù), from 表名;給查詢的某個字段運算后 重新命名(as關(guān)鍵字)
- 英文名:select 字段名1,字段名2 *倍數(shù) as newName from 表名;
- 中文名格式:select 字段名1,字段名2 *倍數(shù) as '中文名' from 表名;
mysql> select * from emp; //
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
mysql> select ename,sal as month,sal*12 as year from emp; //英文重命名
+--------+---------+----------+
| ename | month | year |
+--------+---------+----------+
mysql> select ename,sal as '月薪',sal*12 as '年薪' from emp; //中文重命名
+--------+---------+----------+
| ename | 月薪 | 年薪 |
+--------+---------+----------+
1.2 條件查詢
- 語法格式
select
字段1,字段2,字段3...
from
表名
where
條件(字段名 = 字段數(shù)據(jù));
- 執(zhí)行順序
- 先執(zhí)行from:先明確從哪個位置(哪個表中)查詢數(shù)據(jù)开泽;
- 其次是where:明確查詢的表后牡拇,需要確定查找的具體條件(一般是根據(jù)給定具體值的字段來查找);
- 最后是select:根據(jù)具體的條件"索引"到表中,查詢滿足條件的數(shù)據(jù)惠呼。
- 條件查詢運算符
運算符 | 運算符描述 |
---|---|
= | 等于 |
<>或!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
between … and …. | 兩個值之間导俘,等同于 >= and <= |
is null | 為null(is not null 不為空) |
and | 并且 |
or | 或者 |
in | 包含,相當于多個or(not in不在這個范圍中) |
not | 取非剔蹋,主要用于is not null 或 not in中 |
like | 模糊查詢旅薄,支持%或下劃線匹配;%匹配任意個字符滩租,一個下劃線只匹配一個字符 |
- 注意點
- 查找某個區(qū)段之間的數(shù)據(jù):可以使用大于小于<>號赋秀,也可以使用between and符號(閉區(qū)間),但是between and必須小范圍在前律想,大范圍在后猎莲;
- NULL:在數(shù)據(jù)庫中的NULL并不是一個值(空值),只是一個標記代表該字段沒有數(shù)據(jù)技即,因此判斷一個字段是否為空不能使用 =號著洼,而是使用運算符 is NULL 和 is not NULL;
1.2.1 and 和 or優(yōu)先級
- 優(yōu)先級
當and運算符和or運算符同時出現(xiàn)時而叼,and優(yōu)先級高于or優(yōu)先級身笤,但是對于多個運算符同時出現(xiàn)(且優(yōu)先級不確定時),應(yīng)該使用小括號()將每一部分的運算符括起來葵陵。 - 代碼示例
mysql> select ename,sal,deptno from emp where sal > 1000 and deptno = 20 or deptno = 30;
+--------+---------+--------+
| ename | sal | deptno |
+--------+---------+--------+
| TURNER | 1500.00 | 30 |
| ADAMS | 1100.00 | 20 |
| JAMES | 950.00 | 30 |
| FORD | 3000.00 | 20 |
+--------+---------+--------+
4 rows in set (0.01 sec) //查找出 4條數(shù)據(jù)結(jié)果液荸,有一個工資等于950<sal(1000)
mysql> select ename,sal,deptno from emp where sal>1000 and (deptno=20 or deptno=30);
+--------+---------+--------+
| ename | sal | deptno |
+--------+---------+--------+
| TURNER | 1500.00 | 30 |
| ADAMS | 1100.00 | 20 |
| FORD | 3000.00 | 20 |
+--------+---------+--------+
3 rows in set (0.00 sec) //查找出 3條數(shù)據(jù)結(jié)果
1.2.2 in 運算符
- in 說明:in == 多個or
- in 使用格式
select 字段1,字段2
from 表名
where 條件字段 in(具體值1,具體值2);
//where 條件字段=具體值1 or 條件字段=具體值2脱篙;//上面in方式與or方式相等
- 特點
字段 in(具體值1,具體值2):括號內(nèi)的具體值不是指數(shù)據(jù)在某個范圍內(nèi)娇钱,而是可以取 等于這兩個不同的具體值; - not in:不在指定的具體幾個值當中绊困,和 in相反文搂。
- 使用示例
select * from emp where job = 'SALESMAN' or job = 'MANAGER'; //or寫法
select * from emp where job in('SALESMAN', 'MANAGER'); //in寫法-等同于or
// in后面的值不是區(qū)間,是具體的值秤朗,表示取=800 or或 =5000的值
select ename,job from emp where sal in(800, 5000);
// not in煤蹭,表示不取=1000 or或 =3000的值
select ename,job from emp where sal not in(1000, 3000);
1.2.3 like 模糊查詢
- 說明
使用like模糊查詢的原因是在條件查詢中,并不知道完整的查找條件取视,可能只知道查找條件的一部分硝皂。但是為了能通過這一小部分也可以查詢得到想要的數(shù)據(jù)結(jié)果,就可以使用like 表示查詢條件中未知的一部分作谭。 - like特定符
- %:百分號%代表任意多個字符吧彪,
- _:下劃線_代表任意1個字符,但是指定了下標位置丢早;
- % 與 _ 同時使用:當百分號% 與 下劃線_ 同時使用時姨裸,對下劃線必須使用轉(zhuǎn)移字符 斜線\ 將下劃線轉(zhuǎn)換普通字符秧倾。
- 代碼示例
//找出名字當中含有字母O的
select ename from emp where ename like '%O%';
//找出名字中第二個字母是A的
select ename from emp where ename like '_A%';
//找出名字中有下劃線的
//select name from t_user where name like '%_%'; //錯誤寫法,這樣寫是找出所有name
select name from t_user where name like '%\_%'; //正確寫法
//找出名字中最后一個字母是T的
select ename from emp where ename like '%T';
1.3 排序數(shù)據(jù)
- 說明
對于查找得到的所有數(shù)據(jù)傀缩,希望得到一定順序的輸出結(jié)果那先,因此需要對查找的數(shù)據(jù)進行排序。 - 排序關(guān)鍵字:order by赡艰,默認升序排序售淡。
- 語法格式
//無where子句
select 字段1,字段2,字段3...
from 表名
order by 字段(需是select中的查找字段)
//有where子句(單個字段排序)
select 字段1,字段2,字段3...
from 表名
where 條件(字段名 = 字段數(shù)據(jù));
order by 字段(需是select中的查找字段)
//有where子句(多個字段排序)
select 字段1,字段2,字段3...
from 表名
where 條件(字段名 = 字段數(shù)據(jù));
order by 字段1, 字段2 asc, 字段3 desc
//字段1先默認排序,再字段2 asc升序排序慷垮,最后字段3 desc降序排序
- 執(zhí)行步驟
- 先執(zhí)行from:先明確從哪個位置(哪個表中)查詢數(shù)據(jù)揖闸;
- 其次是where:明確查詢的表后,需要確定查找的具體條件(一般是根據(jù)給定具體值的字段來查找)料身;
- 接著是select:根據(jù)具體的條件"索引"到表中汤纸,查詢滿足條件的數(shù)據(jù);
- 最后是order by:對所有查找到的滿足條件的結(jié)果 進行排序芹血。(order by排序時可能沒有where條件子句也是可行的) 贮泞。
- 特點
- 默認排序:沒有指定排序規(guī)則時,order by默認為升序排序幔烛,也可以在order by字段后面加上 asc為升序排序啃擦,desc為降序排序;
- 多個字段排序:對于給查找的多個字段全部排序時饿悬,會先給寫在最前面的字段先排序令蛉,依次給編寫順序的字段排序;
- 多個字段排序且指定排序順序:給查找的多個字段排序時狡恬,可以通過在order by的每一個字段后面指定asc或desc對每一個字段進行排序言询;
- 多個字段排序主導(dǎo)性:給查找的多個字段排序時,編寫順序越靠前的字段起到主導(dǎo)作用傲宜,只有當前面的字段無法完成排序時,才會啟用后面的字段排序夫啊。
- 代碼示例
//查找所有員工的薪資并排序
select ename , sal from emp order by sal; // 默認升序
select ename , sal from emp order by sal asc; // asc升序
select ename , sal from emp order by sal desc; // desc降序
//按照員工工資的降序排列函卒,當工資相同時按照員工名字升序排列
select ename,sal from emp order by sal desc; //先按照工資降序排列
select ename,sal from emp order by sal desc , ename asc; //在工資降序排列的基礎(chǔ)上 對員工姓名升序排列
1.4 分組函數(shù)
說明
分組函數(shù)又稱為聚合函數(shù)、統(tǒng)計函數(shù)撇眯、組函數(shù)报嵌,主要用于數(shù)據(jù)統(tǒng)計使用。分組函數(shù)可以方便獲得一些特殊數(shù)據(jù)熊榛,如總數(shù)锚国、最大值、最小值玄坦、平均值等血筑。所有的分組函數(shù)都是對"某一組"數(shù)據(jù)進行操作的绘沉。函數(shù)關(guān)鍵字
- count(字段):計數(shù),用于統(tǒng)計數(shù)據(jù)的個數(shù)(一行為一條數(shù)據(jù))豺总,count(*)表示統(tǒng)計數(shù)據(jù)表的所有行數(shù)车伞;
- sum(字段):求和,用于對某個字段的所有數(shù)據(jù)求總和喻喳;
- avg(字段):平均值另玖,用于對某個字段的所有數(shù)據(jù)求平均數(shù);
- max(字段):最大值表伦,用于獲取某一字段中的最大數(shù)谦去;
- min(字段):最小值,用于獲取某一字段中的最小數(shù)蹦哼。
- 語法格式
//求總和
select sum(字段)
from 表名;
//求最大值
select max(字段)
from 表名;
//求最小值
select min(字段)
from 表名;
//求平均值
select avg(字段名)
from 表名;
//求數(shù)據(jù)的條數(shù)(不為NULL的記錄條數(shù))
select count(字段名)
from 表名;
//求表的總行數(shù)(總記錄條數(shù))
select count(*)
from 表名;
- 執(zhí)行原理
- 先執(zhí)行from:先明確從哪個位置(哪個表中)查詢數(shù)據(jù)鳄哭;
- 其次是where:明確查詢的表后,需要確定查找的具體條件(一般是根據(jù)給定具體值的字段來查找)翔怎;
- 最后是select:根據(jù)具體的條件"索引"到表中窃诉,查詢滿足條件的數(shù)據(jù);
- 特點
- 出現(xiàn)位置:分組函數(shù)通常直接出現(xiàn)在select子句中赤套,而不能直接出現(xiàn)在where子句中飘痛;
- 執(zhí)行時間:分組函數(shù)一定是在分組查詢group by進行分組之后才能執(zhí)行;
- 所有的分組函數(shù)都是對"某一組" 或 "某一字段"數(shù)據(jù)進行操作的容握;
- 自動過濾null宣脉;所有的分組函數(shù)使用時會忽略沒有數(shù)據(jù)的字段(即為null的字段),只統(tǒng)計有數(shù)據(jù)的字段(即使為0.0)剔氏;
- 多行處理函數(shù):分組函數(shù)又稱多行處理函數(shù)塑猖,即輸入多行,最終輸出的結(jié)果只有1行谈跛。如sum(字段)是輸入n行數(shù)據(jù)求和得出1行的結(jié)果羊苟,max(字段)是輸入n行的數(shù)據(jù)得出1個/1行的最大數(shù);
- 分組函數(shù)--分組查詢聯(lián)合使用:分組函數(shù)的使用一般都會聯(lián)合分組查詢一起感憾,只有兩個分組聯(lián)合使用才體現(xiàn)出其意義蜡励;
- 所有數(shù)據(jù)庫都有的規(guī)定:只要有NULL參與的運算,結(jié)果一定是NULL阻桅;而分組函數(shù)忽略掉所有NULL凉倚,因此NULL并沒有參與分組函數(shù)的運算。
- 代碼示例
//查詢工資總和
select sum(sal) from emp;
//查詢最高工資
select max(sal) from emp;
//查詢最低工資
select min(sal) from emp;
//查詢平均工資
select avg(sal) from emp;
//查詢總?cè)藬?shù)
//select count(*) from emp; //count(*)表示統(tǒng)計所有行數(shù)/總行數(shù)
select count(ename) from emp;
-
注意點
分組函數(shù)不能直接在where子句當中使用(分組函數(shù)在group by分組之后才能執(zhí)行嫂沉,而where在group by之前執(zhí)行)稽寒。
select 字段 from 表名 where 字段 > avg(字段);//錯誤提示(不合理語句)
select 字段 from 表名 where 字段 > (select avg(字段) from 表名);
1.4.1 單行處理函數(shù)
- 概念
- 多行處理函數(shù):輸入多行數(shù)據(jù)項 最終得出1行數(shù)據(jù)結(jié)果趟章,分組函數(shù)都是多行處理函數(shù)杏糙;
- 單行處理函數(shù):輸入一行數(shù)據(jù)項 得出1行數(shù)據(jù)結(jié)果慎王,輸入多行數(shù)據(jù)項 得出多行數(shù)據(jù)結(jié)果。
- 特點
- 處理精細:對每一行輸入數(shù)據(jù)及時處理搔啊,返回每一個對應(yīng)的處理結(jié)果柬祠。
1.4.2 ifnull()
- 說明
ifnull()屬于單行處理函數(shù),是專門處理數(shù)據(jù)為NULL的空函數(shù)负芋。由于NULL在參與數(shù)學(xué)運算時會將整個數(shù)學(xué)運算結(jié)果變?yōu)閚ull欠雌,為了解決這種情況杂拨,因此使用ifnull()函數(shù)將可能為null的數(shù)據(jù)字段 變?yōu)閿?shù)學(xué)0參與運算。 - 使用格式
ifnull(可能為NULL的字段,期望的處理值):將可能為NULL的字段數(shù)據(jù) 轉(zhuǎn)換成 具體處理值的字段數(shù)據(jù)。 - 特點
- 將分組函數(shù)忽略NULL的特點 轉(zhuǎn)變成 將NULL轉(zhuǎn)換為實際有用的數(shù)據(jù)琅翻;
- 將 讓數(shù)學(xué)運算無效的NULL 轉(zhuǎn)換為 可以讓數(shù)學(xué)運算正常運算的實際數(shù)據(jù)冰寻。
- 代碼示例
//原始查詢--可以為NULL
mysql> select ename,comm from emp;
+--------+---------+
| ename | comm |
+--------+---------+
| SMITH | NULL |
| ALLEN | 300.00 |
| WARD | 500.00 |
| JONES | NULL |
| TURNER | 0.00 |
//計算每個員工的年薪:年薪 = 工資sal + 補貼comm
//select ename,(sal+comm)*12 as yearsal from emp; //comm為NULL時蛇券,參與的運算結(jié)果一定是NULL
//使用ifnull()處理之后--NULL變?yōu)槠谕?
mysql> select ename,ifnull(comm,0) as comm from emp;
+--------+---------+
| ename | comm |
+--------+---------+
| SMITH | 0.00 |
| ALLEN | 300.00 |
| WARD | 500.00 |
| JONES | 0.00 |
| TURNER | 0.00 |
//使用ifnull函數(shù):comm為NULL 變成 comm為0
select ename,(sal+ifnull(comm,0))*12 as yearsal from emp;
1.5 分組查詢
- 說明
分組查詢不同于分組函數(shù)缔恳,分組函數(shù)針對的是對數(shù)據(jù)進行統(tǒng)計/計算處理,而分組查詢是對字段的查詢病袄。 - 分組查詢關(guān)鍵字
- group by:按照某個字段或者某些字段進行分組搂赋,group分組 + by通過分組的字段;
- having:對分組之后的數(shù)據(jù)進行再次過濾(效率較低益缠,不如where子句過濾<where比having先執(zhí)行先過濾>)脑奠。
- 語法格式
5 select 字段1,字段2幅慌,字段3宋欺,分組函數(shù)(字段)...
1 from 表名
2 where 條件子句
3 group by 分組字段
4 having 在分組字段上的條件過濾
6 order by 排序字段
- 執(zhí)行原理
- 首先是from:根據(jù)表名確定在哪個表中查找數(shù)據(jù),確定表永遠是第一步胰伍;
- 第二是where:根據(jù)具體的條件子句在已知表中進行條件過濾齿诞;
- 第三是group by:通過對字段進行分組處理,可以更加明確對分組的條件過濾骂租;
- 第四是having:having是在group by分組之后加上的過濾條件(此過濾效率低下不如where子句過濾)祷杈;
- 第五是select:以上的二到四都是條件過濾,從同時滿足所有過濾條件的字段中 select查找對應(yīng)字段名的數(shù)據(jù)(分組函數(shù)也在此時使用)渗饮;
- 最后是order by:對查找得到的字段數(shù)據(jù)進行排序輸出但汞。
- 特點
- 分組函數(shù)--分組查詢聯(lián)合使用:分組函數(shù)的使用一般都會聯(lián)合分組查詢一起,只有兩個分組聯(lián)合使用才體現(xiàn)出其意義(分組查詢與分組函數(shù)執(zhí)行順序前后的體現(xiàn))抽米;
- 當一條sql語句中使用group by時,select后面只能跟分組函數(shù) 和 參與分組的字段(group by的字段)糙置;
- 當一條sql語句沒有g(shù)roup by時云茸,整張表的數(shù)據(jù)會自成一組。
- 代碼示例
//自成一組:總共14個數(shù)據(jù)
mysql> select * from emp;
+-------+--------+-----------+------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
//分組查詢:先根據(jù)job工種分組谤饭,再求每一個工種的平均薪資(5個工種5個數(shù)據(jù))
mysql> select ename,job,avg(sal) from emp group by job;
+-------+-----------+-------------+
| ename | job | avg(sal) |
+-------+-----------+-------------+
| SCOTT | ANALYST | 3000.000000 |
| SMITH | CLERK | 1037.500000 |
| JONES | MANAGER | 2758.333333 |
| KING | PRESIDENT | 5000.000000 |
| ALLEN | SALESMAN | 1400.000000 |
+-------+-----------+-------------+
//分組查詢:先根據(jù)sal工資分組标捺,再求每一個工資的平均薪資(12種工資12個數(shù)據(jù))
mysql> select ename,job,avg(sal) from emp group by sal;
+--------+-----------+-------------+
| ename | job | avg(sal) |
+--------+-----------+-------------+
| SMITH | CLERK | 800.000000 |
| JAMES | CLERK | 950.000000 |
| ADAMS | CLERK | 1100.000000 |
| WARD | SALESMAN | 1250.000000 |
| MILLER | CLERK | 1300.000000 |
| TURNER | SALESMAN | 1500.000000 |
| ALLEN | SALESMAN | 1600.000000 |
| CLARK | MANAGER | 2450.000000 |
| BLAKE | MANAGER | 2850.000000 |
| JONES | MANAGER | 2975.000000 |
| SCOTT | ANALYST | 3000.000000 |
| KING | PRESIDENT | 5000.000000 |
+--------+-----------+-------------+
//多個字段分組查詢:先根據(jù)deptno部門編號分組懊纳,再根據(jù)工種job在部門分組基礎(chǔ)上分組,最后從具體分好的組中查詢平均薪資
mysql> select deptno,job,avg(sal) from emp group by deptno,job;
+--------+-----------+-------------+
| deptno | job | avg(sal) |
+--------+-----------+-------------+
| 10 | CLERK | 1300.000000 |
| 10 | MANAGER | 2450.000000 |
| 10 | PRESIDENT | 5000.000000 |
| 20 | ANALYST | 3000.000000 |
| 20 | CLERK | 950.000000 |
| 20 | MANAGER | 2975.000000 |
| 30 | CLERK | 950.000000 |
| 30 | MANAGER | 2850.000000 |
| 30 | SALESMAN | 1400.000000 |
+--------+-----------+-------------+
1.5.1 where 與 having
- 執(zhí)行順序
- where:where子句在整個sql語句的第二步開始執(zhí)行亡容,是整個sql中最先進行條件過濾的子句嗤疯;
- having:having在對所有數(shù)據(jù)進行g(shù)roup by分組之后再執(zhí)行,是在分組的基礎(chǔ)上對分組的條件過濾闺兢,而group by在where之后執(zhí)行茂缚。
- 執(zhí)行特點
- where:對于求某單個數(shù)據(jù),可以使用where進行提前過濾屋谭,再執(zhí)行g(shù)roup by分組脚囊,效率較高;
- having: 對于求某個平均數(shù)據(jù)且涉及分組后的平均數(shù)桐磁,可以先進行g(shù)roup by分組再采用having過濾悔耘,因為使用where時會在分組前過濾掉一些數(shù)據(jù)(導(dǎo)致求平均值時不是最終的平均數(shù)據(jù))。
- 代碼示例
//找出每個部門的 最高薪資我擂,要求顯示薪資大于2900的數(shù)據(jù)
//第一步:找出每個部門的最高薪資衬以,將部門分組,求每組部門最高
select max(sal),deptno from emp group by deptno;
//第二步:從每組部門最高校摩,求大于2900的
//select max(sal),deptno from emp group by deptno having max(sal) > 2900; //分組后再過濾
select max(sal),deptno from emp where sal > 2900 group by deptno; //過濾小于2900后再分組
//找出每個部門的 平均薪資看峻,要求顯示薪資大于2000的數(shù)據(jù)
//第一步:找出每個部門的平均薪資,分組部分秧耗,后求平均工資
select deptno,avg(sal) from emp group by deptno;
//第二步:分組求平均數(shù)后备籽,求大于2000的平均數(shù)(不能使用where,where在分組已過濾數(shù)據(jù))
select deptno,avg(sal) from emp group by deptno having avg(sal) > 2000;
1.5.2 distinct關(guān)鍵字(去重查詢)
- 說明
distinct解釋為去重復(fù)分井,在DQL查詢中屬于條件過濾的一種方式车猬,是用來過濾去除一些重復(fù)的數(shù)據(jù)。distinct屬于最后的過濾(distinct關(guān)鍵字在select后面出現(xiàn)尺锚,select是最后執(zhí)行的條件過濾)珠闰。 - 使用格式
select distinct 字段1,字段2瘫辩,...
from 表名
where 條件子句
...
- 特點
- distinct只能用于select子句伏嗜,不能用于其他子句;
- distinct在select子句中只能出現(xiàn)在所有字段的最前面(表示distinct后面的字段全部去重)伐厌;
- 一次過濾去重多個字段承绸,但不能使用括號(),錯誤:select distinct(字段1,字段2)挣轨;
- 一個select子句只能使用一個distinct關(guān)鍵字军熏,錯誤:select distinct 字段1,distinct 字段2;
- 用于統(tǒng)計總類型的個數(shù)(一個類型可能有多個數(shù)據(jù)值卷扮,只求類型<種類>數(shù))荡澎。
- 代碼示例
// 去重:找出emp表中的工種(工種的個數(shù)不變均践,但每個工種有多個職員)
mysql> select distinct(job) from emp;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
+-----------+
//mysql> select ename,distinct(job) from emp; //ERROR: distinct只能出現(xiàn)select子句的首位,所有字段的前面
mysql> select distinct(job),ename from emp;
//mysql> select distinct(job,ename) from emp; //ERROR: distinct每次只能去重一個字段
//mysql> select ename,job form emp where distinct(job); //ERROR: distinct只能出現(xiàn)在select子句摩幔,不能出現(xiàn)其他子句
//mysql> select distinct job,distinct deptno from emp; //ERROR :distinct一次只能出現(xiàn)一個
mysql> select distinct job,deptno from emp; //表示distinct后面的字段全部去重
// 統(tǒng)計崗位的數(shù)量:先去除重復(fù)的崗位彤委,再統(tǒng)計崗位數(shù)量
select count(distinct job) from emp;
1.6 子查詢
- 說明
子查詢是指在一個DQL查詢語句當中插入另外一個查詢語句,具體是在本體的查詢子句中 插入查詢作為該子句的查詢條件或衡。子查詢 即查詢嵌套使用焦影。 - 子查詢關(guān)鍵字
- ()括號:將一個查詢語句封裝在括號中,將括號內(nèi)查詢返回的結(jié)果作為外部查詢的條件薇宠;
- 語法格式
- select 子句子查詢(極少使用偷办,可讀性差)
select
(select 字段 from 表1 where 條件)as 新字段 // 括號內(nèi)子查詢的返回結(jié)果可作為外部查詢的字段
from
表2
where
條件子句;
- from子句子查詢(實際開發(fā)最常使用)
select
別名2.字段
from
(select 字段 from 表1 where 條件)別名2 //括號內(nèi) 子查詢的返回結(jié)果作為新表澄港,且另起別名
where
條件子句椒涯;
- where子句子查詢
select
別名2.字段
from
表2 別名2
where
條件子句 字段1 >=<(select 字段 from 表1 where 條件) //括號內(nèi) 子查詢的返回結(jié)果作為條件子句的一部分條件
- 執(zhí)行原理
- 先執(zhí)行子查詢中的語句
- 再回到外部查詢的from 語句開始
- 特點
先執(zhí)行子查詢,并將子查詢的返回結(jié)果作為外部查詢的字段回梧、臨時表废岂、條件等。 - 代碼示例
1.6.1 表別名
- 概念
在DQL查詢時狱意,通過給每個數(shù)據(jù)表另起別名湖苞,可以讓查詢結(jié)構(gòu)更加清晰易讀,也避免多表查詢時表名過多過長造成的冗余(可讀性差)详囤。 - 起名格式
select
a.字段财骨,b.字段,c.字段
from
表1 別名a藏姐,表2 別名b隆箩,表3 別名c
where
條件子句(過濾條件)
- 使用特點
- 表別名必須在from子句中進行起名(因為所有的DQL查詢語句第一步執(zhí)行的就是from子句)
- 同一張表可以同時起兩個別名,起兩個別名后該兩張表不是"同一張表"(自連接)羔杨;
- 代碼示例
// 原始查詢
select emp.ename, dept.dname //"表名.字段"表達清晰捌臊,但字段太長易混亂
from emp, dept
where emp.deptno=dept.deptno;
// 使用別名查詢
select e.ename, d.dname
from emp e, dept d //使用表別名,方便在其他字段使用
where e.deptno=d.deptno;
1.7 連接查詢
說明
連接查詢又叫跨表查詢兜材,需要關(guān)聯(lián)多個表進行查詢理澎。在日常開發(fā)中極少要求進行單表查詢,一般都是多個表聯(lián)合進行查詢(表與表之間存在聯(lián)系<主鍵曙寡,外鍵>)糠爬,不僅為了數(shù)據(jù)的獨立性,也為了數(shù)據(jù)庫的可維護性更好举庶。連接查詢版本
- SQL92:著重于使用where條件的連接查詢执隧,表連接過濾 和 查詢過濾都在同一個where中使用多個 and進行拼接,可讀性差,過濾條件冗余殴玛;
- SQL99:著重于使用join on表連接條件 + where數(shù)據(jù)查詢條件 分離的查詢,表連接過濾 和 查詢過濾分離添祸,層次更加清晰滚粟。
- 連接查詢分類
- 內(nèi)連接:包括等值連接(等號=)、非等值連接(between...and...)刃泌、自連接凡壤;
- 外連接:包括左外連接、右外連接耙替;
- 全連接:
- 連接查詢原理
- 多個數(shù)據(jù)表聯(lián)合查詢亚侠,區(qū)別于單表查詢;
- 拿單表的一條數(shù)據(jù)(記錄)和另外一張表的數(shù)據(jù)進行匹配俗扇,匹配的上則返回匹配的記錄(有效數(shù)據(jù))硝烂;
- 連接查詢實際原理:多表連接查詢會產(chǎn)生笛卡爾積現(xiàn)象,通過條件篩選铜幽,過濾掉無效數(shù)據(jù)得到有效記錄滞谢,就是多表查詢。
1.7.1 笛卡爾積
- 概念
笛卡爾積又稱笛卡爾乘積現(xiàn)象除抛,指的是在數(shù)據(jù)庫查詢當中進行多表查詢時狮杨,若未對多表聯(lián)查進行條件過濾,則會出現(xiàn)多個重復(fù)且無效的數(shù)據(jù)到忽,并且最終的查詢結(jié)果集等于多個表的數(shù)據(jù)的個數(shù)乘積橄教。 - 實際表示:笛卡爾積 = A表m條記錄 X B表n條記錄
- 處理方式
在查詢中加條件進行過濾可以避免笛卡爾積現(xiàn)象(不會減少記錄的匹配次數(shù),只是顯示有效記錄)
1.7.2 內(nèi)連接(inner join)
- 概念
內(nèi)連接即多表查詢中的單表內(nèi)嵌喘漏,通過在一條查詢語句中進行單表查詢內(nèi)嵌而形成多表查詢的方式护蝶,成為內(nèi)連接。假設(shè)A表和B表進行連接陷遮,凡是A表和B表能夠匹配上的記錄都查詢出來--就是內(nèi)連接滓走。AB兩張表沒有主副之分,兩張表是平等的帽馋。 - 實現(xiàn)方式
將一個查詢拆分"粒度"搅方,將一個多表查詢拆分成多個單表查詢,盡量做到每一個字段出自于對應(yīng)的表绽族,然后使用inner join將單表查詢連接姨涡,從而完成多表查詢。 - 實現(xiàn)關(guān)鍵字:inner join吧慢、on
- 最大特點:只查詢相等的數(shù)據(jù)(連接條件相等的數(shù)據(jù))
-
on關(guān)鍵字
on相當于where關(guān)鍵字涛漂,屬于對查詢的條件過濾,但是on著重于表的連接過濾,where是著重于對查詢的條件過濾匈仗。
on經(jīng)常與inner join同時搭配出現(xiàn)瓢剿,表示在內(nèi)連接過程中的條件過濾或篩選,實現(xiàn)表的連接條件和后來的where查詢條件分離悠轩。 - 語法格式
// 兩張表
select
a.字段1间狂,b.字段2
from
表1 別名a
(inner)join
表2 別名b
on
a.字段 = b.字段; //表1和表2 連接的過濾條件
// 三張或以上多表
select
a.字段1,b.字段2 火架,c.字段3
from
表1 別名a
(inner)join
表2 別名b
on
a.字段 = b.字段; //表1和表2 連接的過濾條件
(inner)join
表3 別名c
on
a.字段 = c.字段; //表1和表3 連接的過濾條件
//....下面可以繼續(xù) join on 或 left/right join on
where
a.字段 = b.字段; //查詢的過濾條件
1.7.2.1 等值連接
- 概念
等值連接是內(nèi)連接中鉴象,連接條件過濾的子句使用 等式= 作為過濾條件的連接。 -
最大特點
表的連接條件是等量關(guān)系(on連接部分是等量關(guān)系)何鸡,A表的主鍵字段的值 = B表的外鍵字段的值纺弊,A表的主鍵必須作為B表的外鍵。 - 語法格式
// 等值連接--SQL92版
select
a.字段1骡男,b.字段2
from
表1 別名a , 表2 別名b
where
a.字段 = b.字段; //查詢的過濾條件
// 等值連接--SQL99版
select
a.字段1淆游,b.字段2
from
表1 別名a
(inner)join
表2 別名b
on
a.字段 = b.字段; // 表連接的 過濾條件
where
a.字段 = b.字段; // 查詢的 過濾條件
- 執(zhí)行順序/原理
1.7.2.2 非等值連接
- 概念
非等值連接是內(nèi)連接中,連接條件過濾的子句使用 beetween and 等作為過濾條件的連接隔盛。 -
最大特點
表的連接條件是非等量關(guān)系(on連接部分是非等量關(guān)系)稽犁。 - 語法格式
// 非等值連接--SQL92版
select
a.字段1,b.字段2
from
表1 別名a , 表2 別名b
where
a.字段 between b.字段 and b.字段;
// 非等值連接--SQL99版
select
a.字段1骚亿,b.字段2
from
表1 別名a
(inner)join //inner可以省略
表2 別名b
on
a.字段 between b.字段 and b.字段; // 表連接的 過濾條件
where
a.字段 = b.字段; // 查詢的 過濾條件
- 執(zhí)行順序/原理
1.7.2.3 自連接
- 概念
自連接指的是對于只有一張表已亥,進行自己連接自己的查詢,將一張表使用兩個"別名"來區(qū)分成兩張表来屠,進而可以篩選過濾虑椎。 -
最大特點
一張表看做兩張表,自己連接自己俱笛,自己查自己捆姜。 - 語法格式
// 自連接:本身是同一張表,使用不同別名作為兩張表
select
a.字段1 as '新字段名'迎膜,b.字段2 as '新字段名'
from
表1 別名a
(inner)join // 表1 連接 表1
表1 別名b
on
a.字段1 = b.字段2; //"兩張表"的字段采用等值連接
- 執(zhí)行順序/原理
- 先對原表起別名
1.7.3 外連接
- 概念
假設(shè)A表和B表進行連接泥技,外連接時A、B兩張表中有一張表是主表磕仅,一張表是副表珊豹,主要查詢主表中的數(shù)據(jù),捎帶著查詢副表榕订。當副表中的數(shù)據(jù)沒有和主表中的數(shù)據(jù)匹配上店茶,副表自動模擬出NULL與之匹配。 - 最大特點
- 主表的數(shù)據(jù)無條件的全部查詢出來劫恒,內(nèi)連接(等值連接)則指查找出字段值相等的數(shù)據(jù)贩幻,當字段值為空或者不相等則不查出轿腺;
- 外連接查詢出來的數(shù)據(jù)會更加完整,內(nèi)連接會丟失數(shù)據(jù)丛楚;
- outer關(guān)鍵字可以省略族壳;
- 筆試最后一題一般是外連接查詢。
- 分類
- 左外連接:以左邊的表為主趣些,無條件查詢出左邊表的所有數(shù)據(jù)記錄决侈;
- 右外連接:以右邊的表為主,無條件查詢出右邊表的所有數(shù)據(jù)記錄喧务;
- 左外連接與右外連接的轉(zhuǎn)換
- 每一個左外連接都必定有一個右外連接的寫法;
// 左外連接
from
表1 a
left outer join // outer可以省略
表2 b
on
a.字段 = b.字段; // 表連接的 過濾條件
// 右外連接
1.7.3.1 左外連接(left join)
- 概念
以左邊的表為主枉圃,連接右邊的表一起查詢功茴,連接查詢的實際原理就是以一張表的數(shù)據(jù)記錄 去匹配另一張表的數(shù)據(jù)記錄。但左外連接使表的連接順序擁有左邊優(yōu)先級孽亲。 -
最大特點
左邊的表是主表坎穿,獲取左表所有記錄,即使右表沒有對應(yīng)匹配的記錄返劲。 - 語法格式
// 左外連接:以左表為主
select
a.字段1 as '新字段1', b.字段2 as '新字段2' //as可以省略
from
表1 a
left outer join // outer可以省略
表2 b
on
a.字段 = b.字段; // 表連接的 過濾條件
where
a.字段 = b.字段; // 數(shù)據(jù)查詢的 過濾條件
- 執(zhí)行順序/原理
1.7.3.2 右外連接(right join)
- 概念
以右邊的表為主玲昧,連接左邊的表一起查詢,連接查詢的實際原理就是以一張表的數(shù)據(jù)記錄 去匹配另一張表的數(shù)據(jù)記錄篮绿。但右外連接使表的連接順序擁有右邊優(yōu)先級孵延。 -
最大特點
右邊的表是主表,用于獲取右表所有記錄亲配,即使左表沒有對應(yīng)匹配的記錄尘应。 - 語法格式
// 右外連接:以右表為主
select
a.字段1 as '新字段1', b.字段2 as '新字段2' //as可以省略
from
表1 a
right outer join // outer是可以省略
表2 b
on
a.字段 = b.字段;
- 執(zhí)行順序/原理
1.7.4 全連接(full join)
- 概念
假設(shè)A表和B表進行連接,外連接時A吼虎、B兩張表都是主表犬钢,沒有副表。查詢時將A思灰、B表的數(shù)據(jù)都無差別查詢出來玷犹。 -
最大特點
每一張表都是主表,沒有副表洒疚。 - 語法格式
- 執(zhí)行順序/原理
1.8 union關(guān)鍵字
- 說明
對于多表查詢或者多個字段查詢歹颓,union關(guān)鍵字是將查詢拆分為多個單一的字段查詢,然后將多個單一查詢的結(jié)果集進行相加油湖,返回一個查詢結(jié)果的合集晴股。 - 最大特點
- 將兩張或多張毫無相關(guān)的表的查詢結(jié)果連接輸出;
- 作用可以取代or 或 in 關(guān)鍵字的部分用法;
- union相加只能是每個查詢是查詢相同的列數(shù)或字段數(shù)肺魁,列數(shù)不同或查詢字段數(shù)不同的多個查詢不能想加电湘;
- 查詢結(jié)果輸出有序(union實則為分步查詢,有先后)。
- 語法格式
// 同表查詢
select 字段1寂呛,字段2 from 表1 where 字段 = '數(shù)據(jù)值1'
union
select 字段1怎诫,字段2 from 表1 where 字段 = '數(shù)據(jù)值2'
// 多表查詢--可以將不同表的查詢結(jié)果 相加結(jié)合輸出
select 字段1,字段2 from 表1 where 字段1 = '數(shù)據(jù)值'
union
select 字段3贷痪,字段4 from 表2 where 字段3 = '數(shù)據(jù)值'
- 執(zhí)行原理 /順序
將一個總的查詢分為多個查詢小分支幻妓,每一個小分支都可以查詢不同的表,最后使用union關(guān)鍵字將每一個小分支的查詢結(jié)果返回作為整個總-查詢的結(jié)果劫拢。 - 代碼示例
- 單表 union相加字段
// 要求:找出工作崗位是SALESMAN和MANAGER的員工
// 使用 or關(guān)鍵字
select ename,job from emp where job = 'MANAGER' or job = 'SALESMAN';
// 使用 in關(guān)鍵字
select ename,job from emp where job in('MANAGER','SALESMAN');
// 輸出結(jié)果無序肉津,查找字段斷續(xù)間接輸出
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
// 使用 union關(guān)鍵字
select ename,job from emp where job = 'MANAGER' // 第一步:先查一個字段
union // 第三步:將結(jié)果相加
select ename,job from emp where job = 'SALESMAN'; //第二步:查另外一個字段
// 查詢結(jié)果相加輸出--字段有序輸出(原因是查詢分步)
+--------+----------+
| ename | job |
+--------+----------+
| JONES | MANAGER |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| MARTIN | SALESMAN |
| TURNER | SALESMAN |
+--------+----------+
- 多表 uinion相加
// 查詢所有員工和部門名稱
mysql> select ename from emp // 第一步:從emp表查詢所有員工
-> union // 第三步:將兩個查詢結(jié)果相加
-> select dname from dept; //第二步:從dept表查詢所有部門
+------------+
| ename |
+------------+
| SMITH |
| ALLEN |
| WARD |
| JONES |
| MARTIN |
| BLAKE |
| CLARK |
| SCOTT |
| KING |
| TURNER |
| ADAMS |
| JAMES |
| FORD |
| MILLER |
| ACCOUNTING |
| RESEARCH |
| SALES |
| OPERATIONS |
+------------+
1.9 limit關(guān)鍵字
- 說明
limit關(guān)鍵字是Mysql中特有的關(guān)鍵字,其他數(shù)據(jù)庫中沒有舱沧,不能通用(Oracle中有一個相同的機制--rownum)妹沙。 - 最大特點
- limit可以實現(xiàn)分頁查詢;
- limit是取出查詢結(jié)果集中的一部分數(shù)據(jù)熟吏;
- limit是整個SQL語句中最后執(zhí)行的一步距糖。
- 語法格式
// startIndex表示起始位置,從下標0開始表示第一條數(shù)據(jù)
// length表示取出結(jié)果集中的 幾個
limit startIndex, length
// 省略startIndex起始位置 時 牵寺,默認從下標0開始取length個數(shù)據(jù)
limit length;
執(zhí)行順序
5 select
字段1悍引,字段2,...
1 from
表1 別名a...
/*(inner/left/right join
表2 別名b
on
表連接條件) // 表連接查詢可有可無帽氓,看具體業(yè)務(wù)
*/
2 where
查詢過濾條件
3 group by
分組字段
4 having
分組的過濾字段
6 order by
排序
7 limit
起始位置趣斤,獲取長度/個數(shù);
- 執(zhí)行原理
在其他所有SQL子句執(zhí)行結(jié)束之后,limit才會執(zhí)行黎休。limit是整個SQL中最后執(zhí)行的一步唬渗,在select子句執(zhí)行之后獲得了查詢結(jié)果在執(zhí)行,是對查詢結(jié)果的過濾奋渔。 - 代碼示例
// emp表中的員工與薪資數(shù)據(jù)--按照降序輸出
mysql> select ename,sal from emp order by sal desc;
+--------+---------+
| ename | sal |
+--------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| MARTIN | 1250.00 |
| WARD | 1250.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| SMITH | 800.00 |
+--------+---------+
// 取出工資排前5名的員工--先對薪資排序
select ename,sal from emp order by sal desc;
// 從排序的薪資中取前5個
select ename,sal from emp order by sal desc limit 0, 5; // 從起始下標0開始镊逝,取5個
select ename,sal from emp order by sal desc limit 5; // 只有一個數(shù)字表示取得長度,默認從下標0開始
// 找出工資排名在第4到第9名的員工
select ename,sal from emp order by sal desc limit 3,6; //下標從0開始
1.9.1 通用分頁SQL
- 分頁原理
每頁顯示3條記錄:起始頁嫉鲸,每頁顯示的數(shù)據(jù)條數(shù)
第1頁:0, 3
第2頁:3, 3
第3頁:6, 3
第4頁:9, 3
第5頁:12, 3 - 分頁實現(xiàn)關(guān)鍵
每頁顯示pageSize條記錄撑蒜;
第pageNo頁:頁碼(pageNo - 1) * pageSize,數(shù)據(jù)條數(shù)pageSize
- pageSize:每頁顯示的多少條記錄
- pageNo:顯示的第幾頁
- java實現(xiàn)分頁
java分頁代碼 {
int pageNo = 2; // 第幾頁:頁碼是2
int pageSize = 10; // 每頁顯示的數(shù)據(jù):10條
String sql = limit (pageNo - 1) * pageSize, pageSize玄渗;// 分頁顯示的頁碼 和當前頁碼顯示的數(shù)據(jù)條數(shù)
}
常見面試題
提供的參考表
dept表
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
emp表
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
salgrade表
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+