5、查詢語句★★★★★★(DQL)
以下是在本次複習中用到的幾張表,如圖所示,表數據sql文件點我查看。
(1)、單表查詢語句及案例
1、基本查詢(最簡單的查詢語句)
select ename from emp;
select ename,sal,comm from emp;
select * from emp;
2、條件查詢
select * from emp where sal>20000;
/**查詢工資高於20000的員工信息**/
select * from emp where sal>=10000 and sal<=30000;
select * from emp where sal between 10000 and 30000;
/**查詢工資在1萬到3萬之間的員工信息**/
select * from emp where job='銷售員' or job='文員';
select * from emp where job in('銷售員','文員');
/**查詢工作是銷售員或文員的**/
select * from emp where hiredate>'2007-01-01' and comm is not null;
/**查詢入職日期晚於2007年1月1日的,並且獎金不是null**/
3、模糊查詢
select * from emp where ename like '___';
/**佔位符查詢,查詢員工名字是三個字的**/
select * from emp where job like '%員%';
/**查詢職位裏帶有‘員’字的**/
(2)、字段控制查詢(select後面可以是字段名、運算,還可以是常量)
1、查詢emp表中員工的工作有哪幾種?
select distinct job from emp;
/**distinct關鍵字用來去重複查詢**/
2、去除null,null和其他數據相加還是null
select ename,sal,comm,(sal+comm),'Test' from emp;
/**查詢每個員工的名字、月薪、獎金、還有月薪獎金和**/
select ename,sal,comm,(sal+ifnull(comm,0)),'TEST' from emp;
/**查詢月薪獎金和時用了判空函數ifnull(非空時的字段名,爲空時需替換爲的值)**/
3、給表或列起別名 as 關鍵字
select ename,sal,comm,(sal+ifnull(comm,0)) as '月薪總和','TEST' as '鬧着玩的' from emp;
/**給字段起別名,也可以查詢不在表中的字段,輸出時會連續輸出這個字段的值**/
select e.ename,e.sal,e.comm,(sal+ifnull(comm,0)) as '月薪總和','TEST' as '鬧着玩的' from emp e;
/**給表emp起別名爲e**/
(3)、查詢時的排序
1、按照工資升序排序,關鍵字:...order by fieldname asc;(asc-->Ascending,升序)
select * from emp order by sal asc;
2、按照入職日期降序排序,關鍵字:...order by fieldname desc;(desc-->Descending,降序)
select * from emp order by hiredate desc;
3、按照入職日期的升序排序,若入職日期一樣,則按工資的降序排
select * from emp order by hiredate asc,sal desc;
4、按照工資高低的降序排序,若工資一樣,則按入職日期升序排
select * from emp order by sal desc,hiredate asc;
(4)、聚合函數查詢,對某列或多個列的數據進行查,常見的聚合函數有 sum avg max min count
1、查詢所有員工的工資和
select sum(sal) from emp;
2、查詢所有員工的獎金和,聚合函數不計算null
select sum(comm) from emp;
3、查詢所有員工的工資和獎金的平均值
select avg(comm) as '獎金平均值',avg(sal) as '工資平均值' from emp;
4、查詢獎金總和的給emp表中所有人的平均值
select sum(comm)/count(empno) from emp;
5、查詢表中共有多少條記錄(若有不爲空的唯一主鍵,建議使用count(主鍵名))
select count(*) as '總記錄數',count(empno) as '主鍵數量'from emp;
(5)、分組函數,分組函數一般與聚合函數一起使用
1、查詢每個部門有多少人數
select job,count(empno) from emp group by job;
2、查詢每個部門有多少人,按部門號分組
select deptno,count(empno) from emp group by deptno;
3、查詢emp表中工資最高的部門,按照部門號分組
select deptno,max(sal) from emp group by deptno;
4、查詢每個部門及部門的工資和,只查詢工資和大於85000的,分組聚合後對整體進行篩選
select deptno,sum(sal) from emp group by deptno having sum(sal)>85000;
/**先分組再篩,此處用到having子句,having是對已經分好組並且計算好的數據進行篩選**/
5、查詢每個部門及部門裏工資大於15000的人數
select deptno,count(ename) from emp where sal>15000 group by deptno;
/**分組加條件,分組前,對參與分組的數據,進行篩選,然後再分組計算,用where子句,即先篩選再分組**/
(6)、分頁查詢,查詢結果集的數據下標是從0開始的,關鍵字: limit(查詢開始的索引,要查幾條),公式:查詢第page頁,每頁顯示pagesize條記錄,則 爲:limit((page-1)*pagesize,pagezize);
1、按照工資降序排序,查詢第一頁,每頁顯示4條記錄
select * from emp order by sal desc limit 0,4;
(7)、單表查詢的模板sql
select 要查的字段 from 表
where 條件
group by 按照分組的字段
having 篩選組的條件
order by 按照排序的字段 desc/asc
limit((第幾頁-1)*每頁幾條記錄,每頁幾條記錄);
(8)、MySQL提供的一些內置函數,這些內部函數可以幫助我們更加方便的處理表中的數據。MySQL函數包括數學函數、字符串函數、日期和時間函數、系統信息函數等。SELECT語句及其條件表達式都可以使用這些函數。同時,INSERT 、UPDATE、DELECT語句及其條件表達式也可以使用這些函數。例如,表中的某個數據是負數,現在需要將這個數據顯示爲正數。這就可以使用絕對值函數。從上面可以知道,MySQL函數可以對錶中數據進行相應的處理,以便得到用戶希望得到的數據。這些函數可以使MySQL數據庫的功能更加強大。下面表中列出了MySQL的內置函數。
a、數學函數,數學函數主要用於處理數字,包括整型、浮點數等。數學函數包括絕對值函數、正弦函數、餘弦函數、獲取隨機數的函數等。
函數名 |
用法 |
作用 |
ABS(X) |
select ABS(-32); |
返回X的絕對值 |
MOD(N,M)或% |
select MOD(15,7); |
返回N被M除的餘數 |
FLOOR(X) |
select FLOOR(1.23); |
返回不大於X的最大整數值 |
CEILING(X) |
select CEILING(1.23); |
返回不小於X的最小整數值 |
ROUND(X) |
select ROUND(1.58); |
返回參數X的四捨五入的一個整數 |
b、字符串函數
函數名 |
用法 |
作用 |
ASCII(str) |
select ASCII('dx') |
返回字符串str的最左面字符的ASCII代碼值。如果str是空字符串,返回0。如果str是NULL,返回NULL。 |
CONCAT(str1,str2,...) |
select CONCAT('My', 'S', 'QL'); |
返回來自於參數連結的字符串。如果任何參數是NULL,返回NULL。可以有超過2個的參數。一個數字參數被變換爲等價的字符串形式。 |
LENGTH(str) |
select LENGTH('text'); |
返回字符串str的長度。 |
LOCATE(substr,str) |
select LOCATE('bar', 'foobarbar'); |
返回子串substr在字符串str第一個出現的位置,如果substr不是在str裏面,返回0. |
INSTR(str,substr) |
select INSTR('foobarbar', 'bar'); |
返回子串substr在字符串str中的第一個出現的位置。 |
LEFT(str,len) |
select LEFT('foobarbar', 5); |
返回字符串str的最左面len個字符。 |
RIGHT(str,len) |
select RIGHT('foobarbar', 4); |
返回字符串str的最右面len個字符。 |
SUBSTRING(str,pos) |
select SUBSTRING('Quadratically',5); |
從字符串str的起始位置pos返回一個子串。 |
TRIM(str) |
select TRIM(' bar '); |
返回字符串str,所有前綴或後綴被刪除了。 |
LTRIM(str) |
select LTRIM(' barbar'); |
返回刪除了其前置空格字符的字符串str。 |
RTRIM(str) |
select RTRIM(‘barbar ’); |
返回刪除了其拖後空格字符的字符串str。 |
REPLACE(str,from_str,to_str) |
select REPLACE('www.mysql.com', 'w', 'Ww'); |
返回字符串str,其字符串from_str的所有出現由字符串to_str代替。 |
REPEAT(str,count) |
select REPEAT('MySQL', 3); |
返回由重複countTimes次的字符串str組成的一個字符串。如果count <= 0,返回一個空字符串。如果str或count是NULL,返回NULL。 |
REVERSE(str) |
select REVERSE('abc'); |
返回顛倒字符順序的字符串str。 |
INSERT(str,pos,len,newstr) |
select INSERT(‘whatareyou', 5, 3, ‘is'); |
返回字符串str,在位置pos起始的子串且len個字符長的子串由字符串newstr代替。 |
c、日期和時間函數
函數名 |
用法 |
作用 |
NOW() |
Select now(); |
以‘YYYY-MM-DD HH:MM:SS’或YYYYMMDDHHMMSS格式返回當前的日期和時間,格式如:2016-01-21 06:48:28 |
CURDATE() |
Select curdate(); |
返回時間的日期,格式如:2016-01-21 |
CURTIME() |
Select curtime(); |
返回時間,格式如:06:48:28
|
DAYOFWEEK(date) |
select DAYOFWEEK('1998-02-03'); |
返回日期date的星期索引(1=星期天,2=星期一, …7=星期六)。 |
DAYOFMONTH(date) |
select DAYOFMONTH('1998-02-03'); |
返回date的月份中的日期,在1到31範圍內。 |
DAYOFYEAR(date) |
select DAYOFYEAR('1998-02-03'); |
返回date在一年中的日數, 在1到366範圍內。 |
DAYNAME(date) |
select DAYNAME("1998-02-05"); |
返回date的星期名字。 |
MONTHNAME(date) |
select MONTHNAME("1998-02-05"); |
返回date的月份名字。 |
d、系統信息函數
函數名 |
用法 |
作用 |
VERSION() |
select version(); |
返回數據庫的版本號。 |
CONNECTION_ID() |
select CONNECTION_ID(); |
返回服務器的連接數,也就是到現在爲止MySQL服務的連接次數; |
DATABASE() |
select database(); |
返回當前數據庫名。 |
LAST_INSERT_ID() |
select LAST_INSERT_ID(); |
返回最後生成的AUTO_INCREMENT值。 |
USER() |
select user(); |
返回用戶名。 |
e、格式化函數
函數名 |
用法 |
作用 |
FORMAT(x,n) |
select format(23.11456,4); |
將數字x進行格式化,將x保留到小數點後n位。這個過程需要進行四捨五入。 |
BIN(x) |
select bin(9); |
返回x的二進制編碼; |
HEX(x) |
select hex(9); |
返回x的十六進制編碼; |
OCT(x) |
select otx(9); |
返回x的八進制編碼; |
CONV(x,f1,f2) |
select conv(9,10,2); |
將x從f1進制數變成f2進制數。 |
(9)、查詢結果集的集合運算
1、並集運算,關鍵字:union,要求被合併的兩個結果:列數、列類型必須要相同
查詢 emp表裏的兩行數據,與dept表裏的兩行數據合併
select ename,job from emp
union
select dname,loc from dept;
2、差集運算,關鍵字:minus,但是MySQL並不支持差集運算
select ename,job from emp
minus
select dname,loc from dept;
3、交集運算,關鍵字:intersect,但是MySQL並不支持交集運算
select ename,job from emp
intersect
select dname,loc from dept;
(10)、連接查詢:內連接、外連接、自然連接★★★★★★
1、內連接:將兩個表簡單的組合在一起,不加條件時,就是兩個表裏的字段數量的乘積
select * from emp,dept; -- >這句是MySQL的方言,oracle裏不支持
select * from emp e inner join dept d;
2、內連接的sql語句寫法,與上面兩句功能一樣
select * from emp,dept where emp.deptno=dept.deptno;
select * from emp e inner join dept d where e.deptno=d.deptno;
3、查詢‘甘寧’所在部門的部門號、部門名稱
select e.ename,e.deptno,d.dname from emp e,dept d
where e.deptno=d.deptno and e.ename='甘寧';
4、查詢‘張二’所在的部門號和部門名稱
select e.ename,e.deptno,d.dname from
emp e inner join dept d
where e.deptno=d.deptno and e.ename='張二';
5、外連接查詢,就是以某個表爲主要查詢表,分爲左連接和右連接
(1)、左連接:左表 left join 右表,左表裏的數據必定會查出,右表裏沒有的數據對應爲null
select e.ename,e.deptno,d.dname from
emp e left join dept d on e.deptno=d.deptno
where e.ename='張二';
(2)、右連接,左表 right join 右表,右表裏的數據一定會查出,左表裏沒有的數據對應爲null
select * from emp e
right join dept d on d.deptno=e.deptno;
6、自然連接,系統自動找到兩個表關聯的連接字段,然後做內連接形式的查詢
select * from emp e
natural join dept d;
/**注意:上述各示例中出項的形如“emp e”,這些語句等同於“emp as e”,是給表起別名,省略關鍵字的效果,也可以不起別名**/
(11)、連接查詢的練習
1、查詢公司在各個城市的員工人數
select d.loc,count(e.empno) from dept d left join emp e
on e.deptno=d.deptno group by d.loc;
/**因爲地點必須要查出,所以選擇dept左連接emp表,這樣,dept表中的數據會確保都被查出**/
或者用右連接的方式
select d.loc,count(e.empno) from emp e right join dept d
on e.deptno=d.deptno group by d.loc;
2、查詢所有銷售員或分析師的名字、月薪、部門號和部門名
select e.ename,e.sal,e.deptno,d.dname from
emp e left join dept d on e.deptno=d.deptno
where e.job in('銷售員','分析師');
3、查詢公司所有部門號,部門名,及這個部門中工資+獎金和大於2萬的人數,並降序排序
select d.deptno,d.dname,count(e.empno) from
dept d left join emp e on e.deptno=d.deptno
where (ifnull(sal,0)+ifnull(comm,0))>20000 or (d.deptno is not null and e.empno is null)
group by d.deptno
order by count(e.empno) desc;
/**因部門號爲40的這個部門裏沒人,所以需要在where條件判斷完工資後再加(d.deptno is not null and e.empno is null)這句,目的是隻要這個部門號存在,不爲空,就進入分組**/
4、表的自關聯查詢,查詢每個員工的名字、入職日期,直接上司的名字、上司的入職日期
select e.ename,e.hiredate,m.ename,m.hiredate from
emp e left join emp m on e.mgr=m.empno;
或者用右連接的方式
select e.ename,e.hiredate,m.ename,m.hiredate from
emp m right join emp e on m.empno=e.mgr;
5、查詢員工入職日期早於上司入職日期的員工
select e.ename,e.hiredate,m.ename,m.hiredate from
emp e left join emp m on e.mgr=m.empno
where e.hiredate<m.hiredate;
6、三表查詢,查詢員工入職日期早於上司入職日期的員工姓名、入職日期、上司名、上司入職日期、員工部門
號和員工所在地
select e.ename,e.hiredate,m.ename,m.hiredate,e.deptno,d.loc from
emp e left join emp m on e.mgr=m.empno left join dept d on e.deptno=d.deptno
where e.hiredate<m.hiredate;
/**這裏是三表聯查,若還有其他表參與則繼續向後追加連接即可**/
(12)、子查詢,一個select語句裏的查詢條件可能來自於另外一個查詢,或者是一個select語句裏的查詢列們中的某個列或多個列可能來自另外一個查詢的結果表中
1、查詢工資大於‘關羽’的員工名字和工資
①:select ename,sal from emp where ename='關羽';
②:select ename,sal from emp where sal>(select sal from emp where ename='關羽');
2、查詢工資大於20部門任何人工資的人的名字和工資
①:select sal from emp where deptno=20;
②:select ename,sal from emp where sal> all(select sal from emp where deptno=20);
/**all相當於max**/
select ename,sal from emp where sal> any(select sal from emp where deptno=20);
/**順便補充下any函數的作用, any相當於min**/
3、查詢‘增阿牛’的部門號,部門名,以及他的下屬名,下屬部門名
①:查‘增阿牛’的部門號和部門名
select e.ename,e.empno,e.deptno,d.dname from
emp e left join dept d on e.deptno=d.deptno where e.ename='增阿牛';
②:select e.ename as '下屬名字',d.dname as '下屬部門名稱',m.ename as '上司名字',m.dname as '上司部門名稱' from
emp e left join dept d on e.deptno=d.deptno
left join (select e.ename,e.empno,e.deptno,d.dname from
emp e left join dept d on e.deptno=d.deptno where e.ename='增阿牛') m on m.empno=e.mgr
where m.ename is not null;
(13)、case when then else end 語句,類似於Java中的switch語句
1、本月要給員工加薪,如果工資小於2萬,翻5倍;2萬<sal<3萬的,翻2倍;sal>3萬的,不變,請查詢員工本月工資和漲幅
select ename,sal,(
case
when sal<20000 then sal*5
when sal>20000 and sal<30000 then sal*2
else sal
end
) as '本月工資' from emp;
2、查詢文員的人數和銷售員的人數
select job,count(*) from emp group by job having job in('文員','銷售員');
/**方法1(兩行顯示)**/
select sum(
case
when job='文員' then 1
else 0
end
) as 文員人數,sum(
case
when job='銷售員' then 1
else 0
end
) as 銷售員人數 from emp;
/**方法2(一行顯示):**/