1. 程式人生 > 實用技巧 >03、MySQL常見函式、分組函式、分組查詢

03、MySQL常見函式、分組函式、分組查詢

目錄

常見函式

#進階四、函式
/*
函式;類似於Java中的"方法"
為了解決某個問題,將編寫的一系列命令集合封裝在一起,對外僅僅暴露方法名以供外部呼叫
1、自定義方法(函式)
2、呼叫方法(函式)

常見函式:
1、字元函式
2、數學函式
3、日期函式
4、流程控制函式
*/

-- 1、字元函式
#concat 拼接
SELECT CONCAT('Hello,', first_name, last_name) AS str FROM employees;

#length 獲取位元組長度,由字符集決定
SELECT LENGTH('中國Hello');
#11=6+5

#char_length 獲取字元長度
SELECT CHAR_LENGTH('Hello中國');
#7

#substring 擷取字串 SQL中字串的起始索引從1開始
SELECT SUBSTRING('Hello,MySQL', 7);
#MySQL  7代表開始索引
SELECT SUBSTRING('Hello,MySQL', 1, 5);
#Hello  1代表起始索引,5代表擷取的個數

#instr 返回字串第一次出現的索引
SELECT INSTR('Hello,Hello', 'llo');
#3

#trim 去除前後空格
SELECT TRIM('    JavaScript    ');
SELECT TRIM('x' FROM 'xxxxxJavaxxxxx');
#Java

# lpad 左填充
SELECT LPAD('Script', 3, 'x');
#為Script左填充x直到3位
#Scr
# rpad 右填充
SELECT RPAD('Java', 5, 'b');
#為Java右填充b直到5位
#Javab

#查詢員工表中的姓名:姓首字母大寫,其他字母小寫,名所有字母大寫,姓與名之間用_拼接,最後起別名
SELECT CONCAT(UPPER(SUBSTRING(first_name, 1, 1)), LOWER(SUBSTRING(first_name, 2)), '_', UPPER(last_name)) AS finalname
FROM employees;

# strcmp 比較兩個字串的大小
SELECT STRCMP('ABC', 'AAA');
#1

# left right
SELECT LEFT('ShawnYue', 5);
#Shawn
SELECT RIGHT('ShawnYue', 3);
#Yue

-- 2、數學函式
#abs 取絕對值
SELECT ABS(-2);
#2

#ceil 向上取整
SELECT CEIL(1.2);
#2
SELECT CEIL(1.12);
#2

#floor 向下取整
SELECT FLOOR(1.78);
#1

#round 四捨五入
SELECT ROUND(1.12);
#1
SELECT ROUND(1.50);
#2

SELECT ROUND(1.87232, 2);
#保留小數點後2位
#1.87

# truncate 截斷
SELECT TRUNCATE(1.87121, 2);
#1.87


# mod 取餘
SELECT MOD(10, 3);
#1
#餘數的正負只與被除數有關

-- 3、日期函式
#now 獲取當前日期時間
SELECT NOW();
#2020-07-22 21:33:38

#curdate 獲取當前日期
SELECT CURDATE();
#2020-07-22

#curtime 獲取當前時間
SELECT CURTIME();
#21:35:06

#datediff 獲取兩個日期的差
SELECT DATEDIFF(CURDATE(), '1998-11-08');
#7928

#date_format 格式化日期
SELECT DATE_FORMAT(CURDATE(), '%Y年%m月%d日');
#2020年07月23日

SELECT DATE_FORMAT(hiredate, '%Y年%m月%d日 %H時%i分%s秒') FROM employees;

#str 解析字串
SELECT STR_TO_DATE('2019年7月1日', '%Y年%m月%d日');
#2019-07-01

-- 4、流程控制函式
# if函式
SELECT IF(100 > 90, '大於', '小於');
#大於

SELECT IF(commission_pct IS NOT NULL, salary * 12 * (1 + commission_pct) ,'沒獎金')
FROM employees;

# case函式
/*
CASE 表示式
WHEN 值1 THEN 結果1
WHEN 值2 THEN 結果2
...
ELSE 結果n
END
*/
#部門編號為30,工資顯示為double;部門編號為50,工資顯示為triple;部門編號為60,工資顯示為quadra;否則不變
SELECT department_id, salary,
(CASE department_id
WHEN 30 THEN salary * 2
WHEN 50 THEN salary * 3
WHEN 60 THEN salary * 4
ELSE salary
END) newSalary
FROM employees;


/*
CASE
WHEN 條件一 THEN 結果1
WHEN 條件二 THEN 結果2
...
ELSE 結果n
END
*/
#如果工資大於2w,顯示級別為A;大於1.5w,顯示級別為B;大於1w,顯示級別為C;否則顯示D
SELECT salary,
(CASE 
WHEN salary > 20000 THEN 'A'
WHEN salary > 15000 THEN 'B'
WHEN salary > 10000 THEN 'C'
ELSE 'D'
END) grade
FROM employees;

#將員工按首字母排序和姓名的長度排序
SELECT last_name, CHAR_LENGTH(last_name) len
FROM employees
ORDER BY SUBSTRING(last_name, 1, 1) ASC, len ASC;

分組函式

#進階5、分組函式/聚合函式/統計函式
/*
分組函式往往用於將一組資料進行統計計算,最終得到一個值,所以又稱聚合函式/統計函式。
1、常見的分組函式,sum()求和、avg()求平均數、max()求最大值、min()求最小值、count()計算非空欄位值的個數
*/
#查詢所有員工的工資和、工資平均值、最高工資、最低工資、有工資的個數
SELECT SUM(salary) 工資和, AVG(salary) 平均工資, MAX(salary) 最大工資, MIN(salary) 最低工資, COUNT(salary) 個數
FROM employees;
-- 工資和	平均工資	最大工資	最低工資	個數
-- 691400.00	6461.682243	24000.00	2100.00		107

SELECT MAX(last_name) FROM employees;
#Zlotkey
#按照字串的字典順序排序

SELECT MIN(last_name) FROM employees;
#Abel

#查詢員工表中有獎金的人數
SELECT COUNT(commission_pct) FROM employees;
#35

#查詢員工表中月薪大於5000的人數
SELECT COUNT(salary) FROM employees WHERE salary > 5000;
#58

#查詢有領導的人數
SELECT COUNT(manager_id) FROM employees;
#106

#count的補充介紹
/*
count計算非空欄位的個數
*/
SELECT COUNT(*) FROM employees;
#107 統計結果集的行數
#有一列資料不為NULL,就統計,除非某一行所有列都為NULL

SELECT COUNT(1) FROM employees;
#107
#和count(*)一致

#推薦使用count(*)

#搭配distinct使用
#查詢有員工的部門個數
SELECT COUNT(DISTINCT department_id)
FROM employees;

分組查詢

#進階六、分組查詢
/*
語法:
select 查詢列表
from 表名
where 篩選條件
group by 分組列表;

1、特點:查詢列表往往是分組函式或者分組的欄位;
2、分組查詢分為兩類:(1):分組前篩選where,在group by之前;(2)分組後篩選having,在group by之後
*/
#計算每個工種的員工平均工資
SELECT AVG(salary) 平均工資, job_id
FROM employees
GROUP BY job_id;

#查詢每個領導下的員工個數
SELECT manager_id, COUNT(*) 個 FROM employees GROUP BY manager_id;

#查詢郵箱中包含a字元的部門的最高工資
SELECT department_id 部門編號, MAX(salary) 最高工資
FROM employees
WHERE email LIKE '%a%' AND department_id IS NOT NULL
GROUP BY department_id;


-- 分組前的篩選:where子句在group by之前執行
#查詢每個領導下有獎金的員工的平均工資
SELECT manager_id 領導編號, TRUNCATE(AVG(salary), 2) 員工平均工資
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY manager_id;


-- 分組後的篩選:having子句在group by之後執行
#查詢哪個部門的員工個數大於5
/*
錯誤版:
select department_id 部門, COUNT(*) 員工個數
from employees
where COUNT(*) > 5
group by department_id;
*/
# where後面不能使用分組函式
SELECT department_id 部門, COUNT(*) 員工個數
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5;
# having後面可以使用分組函式


#每個工種有獎金的員工的最高工資>12000的工種編號和最高工資
SELECT job_id 工種編號, MAX(salary) 最高工資
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary) > 12000;

#領導編號>102的每個領導手下員工的最低工資大於5000的最低工資
SELECT manager_id 領導編號, MIN(salary) 最低工資
FROM employees
WHERE manager_id > 102
GROUP BY manager_id
HAVING MIN(salary) > 5000;

#每個工種有獎金的員工的最高工資>6000的工種編號和最高工資,並按最高工資降序
SELECT job_id 工種編號, MAX(salary) 最高工資
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary) > 6000
ORDER BY 最高工資 DESC;

-- 按多個欄位分組
#查詢每個工種每個部門的最低工資,並按最低工資降序
SELECT MIN(salary) 最低工資, job_id 工種編號, department_id 部門編號
FROM employees
GROUP BY job_id, department_id
ORDER BY 最低工資 DESC;
#工種一樣,部門一樣的才算做一組員工

/*
執行順序:
1、from子句
2、where子句
3、group by子句
4、having子句
5、select子句
6、order by子句
*/