Browse Source

'message'

machinecat520 2 years ago
parent
commit
bef7e03ba4

+ 277 - 0
第七章、单行函数.sql

@@ -0,0 +1,277 @@
+#第七章、单行函数
+
+#1、数值函数
+#基本操作
+SELECT ABS(-123),ABS(32),SIGN(43),PI(),CEIL(32.32),CEILING(-43.23),FLOOR(32.32),FLOOR(-43.23),MOD(12,5)
+FROM DUAL;
+
+#取随机数
+SELECT RAND(),RAND(),RAND(10),RAND(10),RAND(-1),RAND(-1)
+FROM DUAL;
+
+#四舍五入、截断操作
+SELECT ROUND(123.456),ROUND(123.456,0),ROUND(123.456,1),ROUND(123.456,2),
+ROUND(123.456,-1),ROUND(153.456,-2)
+FROM DUAL;
+
+SELECT TRUNCATE(123.456,0),TRUNCATE(123.496,1),TRUNCATE(129.45,-1)
+FROM DUAL;
+
+#单行函数可以嵌套
+SELECT TRUNCATE(ROUND(123.456,2),0)
+FROM DUAL;
+
+#角度与弧度的互换
+SELECT RADIANS(30),RADIANS(45),RADIANS(60),RADIANS(90)
+FROM DUAL;
+
+SELECT DEGREES(2*PI()),DEGREES(RADIANS(60))
+FROM DUAL;
+
+#三角函数
+SELECT SIN(RADIANS(30)),DEGREES(ASIN(1)),TAN(RADIANS(45)),DEGREES(ATAN(1))
+FROM DUAL;
+
+#指数和对数
+SELECT POW(2,5),POWER(2,4),EXP(2)
+FROM DUAL;
+
+SELECT LN(EXP(2)),LOG(EXP(2)),LOG10(10),LOG2(4)
+FROM DUAL;
+
+#进制间的转换
+SELECT BIN(10),HEX(10),OCT(10),CONV(10,2,8),CONV(10,10,8)
+FROM DUAL;
+
+#2、字符串函数
+SELECT ASCII('abc'),CHAR_LENGTH('hello'),CHAR_LENGTH('我们'),LENGTH('hello'),LENGTH('我们')
+FROM DUAL;
+
+# xxx worked for yyy
+SELECT CONCAT(emp.last_name,' worked for ',mgr.last_name) "details"
+FROM employees emp JOIN employees mgr
+WHERE emp.manager_id = mgr.employee_id;
+
+SELECT CONCAT_WS('-','hello','world','hello','beijing')
+FROM DUAL;
+
+#字符串的索引是从1开始的
+SELECT INSERT('helloworld',2,3,'aaaaa'),REPLACE('hello','ll','mmm')
+FROM DUAL;
+
+SELECT REPLACE('hello','lol','mmm')
+FROM DUAL;
+
+SELECT UPPER('Hello'),LOWER('heLLo')
+FROM DUAL;
+
+SELECT last_name,salary
+FROM employees
+WHERE LOWER(last_name) = 'king';
+
+SELECT LEFT('hello',2),LEFT('hello',12),RIGHT('hello',3),RIGHT('hello',13)
+FROM DUAL;
+
+#LPAD:实现右对齐效果
+#RPAD:实现左对齐效果
+
+SELECT employee_id,last_name,LPAD(salary,10,'*')
+FROM employees;
+
+SELECT CONCAT('---',TRIM('   he  l  l o  '),'***'),TRIM('oo' FROM 'ooheollo')
+FROM DUAL;
+
+SELECT REPEAT('hello',4),LENGTH(SPACE(5)),STRCMP('abc','abd')
+FROM DUAL;
+
+SELECT SUBSTR('hello',2,2),LOCATE('ll','hello')
+FROM DUAL;
+
+SELECT ELT(2,'aa','bb','cc','dd'),FIELD('mm','gg','jj','mm','dd','mm'),FIND_IN_SET('mm','gg,mm,jj,dd,mm,gg')
+FROM DUAL;
+
+SELECT employee_id,NULLIF(LENGTH(first_name),LENGTH(last_name)) "compare"
+FROM employees;
+
+#3、日期和时间函数
+#3.1、获取日期、时间
+SELECT CURDATE(),CURRENT_DATE(),CURTIME(),NOW(),SYSDATE(),UTC_DATE(),UTC_TIME()
+FROM DUAL;
+
+SELECT CURDATE(),CURDATE() + 0,CURTIME(),CURTIME() + 0,NOW(),NOW() + 0
+FROM DUAL;
+
+#3.2、日期与时间戳的转换
+SELECT UNIX_TIMESTAMP(),UNIX_TIMESTAMP('2022-11-14 23:45:32'),FROM_UNIXTIME(1669634117),FROM_UNIXTIME(1668440732)
+FROM DUAL;
+
+#3.3、获取月份、星期、星期数、天数等函数
+SELECT YEAR(CURDATE()),MONTH(CURDATE()),DAY(CURDATE()),HOUR(CURTIME()),MINUTE(CURTIME()),SECOND(CURTIME())
+FROM DUAL;
+
+#以下日期类型存在隐式转换,将字符串转换成日期类型
+SELECT MONTHNAME('2022-11-14'),DAYNAME('2022-11-14'),WEEKDAY('2022-11-14'),QUARTER(CURDATE()),WEEK(CURDATE()),DAYOFYEAR(NOW()),DAYOFMONTH(NOW()),DAYOFWEEK(NOW())
+FROM DUAL;
+
+#3.4、日期的操作函数
+SELECT EXTRACT(SECOND FROM NOW()),EXTRACT(DAY FROM NOW()),EXTRACT(HOUR_MINUTE FROM NOW()),EXTRACT(QUARTER FROM '2022-11-14')
+FROM DUAL;
+
+#3.5、时间和秒钟转换的函数
+SELECT TIME_TO_SEC(CURTIME()),SEC_TO_TIME(71239)
+FROM DUAL
+
+#3.6、计算日期和时间的函数
+SELECT NOW(),DATE_ADD(NOW(),INTERVAL 1 YEAR),DATE_ADD(NOW(),INTERVAL -1 YEAR),DATE_SUB(NOW(),INTERVAL 1 YEAR)
+FROM DUAL;
+
+SELECT DATE_ADD(NOW(),INTERVAL 1 DAY) AS addDay,DATE_ADD('2022-11-14 23:32:12',INTERVAL 10 SECOND) AS addSecond,ADDDATE('2022-11-14 23:32:12',INTERVAL 10 SECOND) AS addSecond2,DATE_ADD('2022-11-14 23:32:12',INTERVAL '10_10' MINUTE_SECOND) AS addMS,DATE_ADD(NOW(),INTERVAL -1 YEAR) AS addY,DATE_ADD(NOW(),INTERVAL '10_10' YEAR_MONTH) AS addYM
+FROM DUAL;
+
+SELECT DATE_SUB('2022-11-14',INTERVAL 28 DAY) AS col1,SUBDATE('2022-11-14',INTERVAL 28 DAY) AS col2,DATE_SUB('2022-11-14 13:32:45',INTERVAL '1_1' DAY_HOUR) AS col3
+FROM DUAL;
+
+SELECT ADDTIME(NOW(),20),SUBTIME(NOW(),30),SUBTIME(NOW(),'1:1:3'),DATEDIFF(NOW(),'2022-11-14'),TIMEDIFF(NOW(),'2022-11-14 22:10:10')
+FROM DUAL;
+
+SELECT FROM_DAYS(366),TO_DAYS('0000-12-25'),LAST_DAY(NOW()),MAKEDATE(YEAR(NOW()),12),MAKETIME(10,21,23),PERIOD_ADD(20200101010101,10)
+FROM DUAL;
+
+#3.7、日期的格式化与解析
+#格式化:日期 ---> 字符串
+#解析:	字符串 ---> 日期
+
+#此时我们谈的是日期的显式格式化和解析
+
+#格式化
+SELECT DATE_FORMAT(CURDATE(),'%Y-%M-%D') AS col1,DATE_FORMAT(NOW(),'%y-%m-%d') AS col2,TIME_FORMAT(CURTIME(),'%h:%i:%s') AS col3,DATE_FORMAT(NOW(),'%Y-%m-%d %h:%i:%s %W %w %T %r') AS col4
+FROM DUAL;
+
+#解析:格式化的逆过程
+SELECT STR_TO_DATE('2022-11-29 10:13:49 Tuesday 2 10:13:49 10:13:49 AM','%Y-%m-%d %h:%i:%s %W %w %T %r') AS col
+FROM DUAL
+
+SELECT GET_FORMAT(DATE, 'USA')
+FROM DUAL;
+
+SELECT DATE_FORMAT(CURDATE(),GET_FORMAT(DATE, 'USA'))
+FROM DUAL;
+
+#4、流程控制函数
+#4.1、IF(value,value1,value2)
+SELECT last_name,salary,IF(salary > 6000,'高工资','低工资') "details"
+FROM employees;
+
+SELECT last_name,commission_pct,IF(commission_pct IS NOT NULL,commission_pct,0) "details",salary * 12 * (1+IF(commission_pct IS NOT NULL,commission_pct,0)) "annual_sal"
+FROM employees;
+
+#4.2、IFNULL(value1,value2):看做是IF(value,value1,value2)的特殊情况
+SELECT last_name,commission_pct,IFNULL(commission_pct,0) "details"
+FROM employees;
+
+#4.3、CASE WHEN...THEN...WHEN...THEN...END
+SELECT last_name,salary,CASE WHEN salary >= 15000 THEN '白骨精'
+														 WHEN salary >= 10000 THEN '潜力股'
+														 WHEN salary >= 8000 THEN '小屌丝'
+														 ELSE '草根' END AS "details",department_id
+FROM employees;
+
+SELECT last_name,salary,CASE WHEN salary >= 15000 THEN '白骨精'
+														 WHEN salary >= 10000 THEN '潜力股'
+														 WHEN salary >= 8000 THEN '小屌丝'
+														 END AS "details",department_id
+FROM employees;
+
+#4.4、CASE...WHEN...THEN...WHEN...THEN...END
+#相当于Java的switch…case…
+/*
+练习1
+查询部门号为10,20,30的员工信息,
+若部门号为10,则打印其工资的1.1倍,
+若部门号为20,则打印其工资的1.2倍,
+若部门号为30,则打印其工资的1.3倍,
+其他部门,则打印其工资的1.4倍。
+*/
+
+SELECT employee_id,last_name,department_id,salary,
+CASE department_id
+	WHEN 10 THEN salary*1.1
+	WHEN 20 THEN salary*1.2
+	WHEN 30 THEN salary*1.3
+	ELSE salary*1.4 END "details"
+FROM employees;
+
+
+/*
+练习2:
+查询部门号为10,20,30的员工信息,
+若部门号为10,则打印其工资的1.1倍,
+若部门号为20,则打印其工资的1.2倍,
+若部门号为30,则打印其工资的1.3倍
+*/
+
+SELECT employee_id,last_name,department_id,salary,
+CASE department_id
+	WHEN 10 THEN salary*1.1
+	WHEN 20 THEN salary*1.2
+	WHEN 30 THEN salary*1.3
+	END "details"
+FROM employees
+WHERE department_id IN(10,20,30);
+
+#5、加密与解密的函数
+#PASSWORD():在MySQL8.0中已被弃用,在MySQL5.7中可正常使用
+-- SELECT PASSWORD('mysql')
+-- FROM DUAL;
+
+SELECT MD5('mysql'),SHA('mysql')
+FROM DUAL;
+
+#ENCODE()/DECODE():在MySQL8.0中弃用,在MySQL5.7中可正常使用
+
+-- SELECT ENCODE('atguigu','mysql'),DECODE(ENCODE('atguigu','mysql'),'mysql')
+-- FROM DUAL;
+
+#6、MySQL信息函数
+SELECT VERSION(),CONNECTION_ID(),DATABASE(),SCHEMA(),USER(),CURRENT_USER(),CHARSET('世界杯'),COLLATION('世界杯')
+FROM DUAL;
+
+#7、其他函数
+#如果n的值小于或者等于0,则只保留整数部分
+SELECT FORMAT(123.125,2),FORMAT(123.125,0),FORMAT(123.125,-2)
+FROM DUAL;
+
+SELECT CONV(16,10,2),CONV(8888,10,16),CONV(NULL,10,2)
+FROM DUAL;
+
+#以“192.168.1.100”为例,计算方式为192乘以256的3次方,加上168乘以256的2次方,加上1乘以256,再加上100
+SELECT INET_ATON('192.168.1.100'),INET_NTOA(3232235876)
+FROM DUAL;
+
+#BENCHMARK(n,expr):用于测试表达式的执行效率
+SELECT BENCHMARK(1000000,MD5('mysql'))
+FROM DUAL;
+
+#CONVERT():可以实现字符集的转换
+SELECT CHARSET('atguigu'),CHARSET(CONVERT('atguigu' USING 'gbk'))
+FROM DUAL;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 85 - 0
第七章、练习题.sql

@@ -0,0 +1,85 @@
+#第七章、练习题
+
+#1、显示系统时间(注:日期+时间)
+SELECT NOW(),SYSDATE(),CURRENT_TIMESTAMP(),LOCALTIME(),LOCALTIMESTAMP()
+FROM DUAL;
+
+#2、查询员工号,姓名,工资,以及工资提高20%后的结果(new salary)
+SELECT employee_id,last_name,salary,salary*1.2 AS "new salary"
+FROM employees;
+
+#3、将员工的姓名按首字母排序,并写出姓名的长度(length)
+SELECT last_name,LEFT(last_name,1) ,LENGTH(last_name) AS length
+FROM employees
+#ORDER BY LEFT(last_name,1);
+ORDER BY last_name ASC;#老师做的
+
+#4、查询员工id,last_name,salary,并作为一个列输出,别名为OUT_PUT
+SELECT CONCAT_WS('-',employee_id,last_name,salary) AS OUT_PUT
+FROM employees;
+
+#老师做的
+SELECT CONCAT(employee_id,',',last_name,',',salary) AS "OUT_PUT"
+FROM employees;
+
+#5、查询公司各员工工作的年数、工作的天数,并按工作年数的降序排序
+SELECT last_name,hire_date,DATEDIFF(NOW(),hire_date)/365 AS "workYears",DATEDIFF(NOW(),hire_date) AS "workDay"
+FROM employees
+ORDER BY workYears DESC;
+
+#老师做的
+SELECT employee_id,DATEDIFF(CURDATE(),hire_date)/365 "worked_years",DATEDIFF(CURDATE(),hire_date) "worked_days",TO_DAYS(CURDATE()) - TO_DAYS(hire_date) "worked_days1"
+FROM employees
+ORDER BY worked_years DESC;
+
+#6、查询员工姓名,hire_date,department_id,满足以下条件:
+#雇佣时间在1997年之后,department_id为80或90或100,commission_pct不为空。
+SELECT last_name,hire_date,department_id
+FROM employees
+WHERE department_id IN(80,90,100)
+AND commission_pct IS NOT NULL
+AND DATE_FORMAT(hire_date,'%Y') >= '1997';
+
+#老师做的
+SELECT last_name,hire_date,department_id
+FROM employees
+WHERE department_id IN(80,90,100)
+AND commission_pct IS NOT NULL
+#AND hire_date >= '1997';#也可以写成这样,但是日期最好写完整,否则容易出错
+#AND hire_date >= '1997-01-01';#隐式转换
+#AND DATE_FORMAT(hire_date,'%Y-%m-%d') >= '1997-01-01'; #显式转换操作,格式化:日期 ---> 字符串
+#AND DATE_FORMAT(hire_date,'%Y') >= '1997';#显式转换操作,格式化
+AND hire_date >= STR_TO_DATE('1997-01-01','%Y-%m-%d');# 显式转换操作,解析:字符串 ---> 日期
+
+#7、查询公司中入职超过10000天的员工姓名、入职时间
+SELECT last_name,hire_date,DATEDIFF(NOW(),hire_date) AS "workDays"
+FROM employees
+WHERE DATEDIFF(NOW(),hire_date) >= 10000;
+
+#8、做一个查询,产生下面的结果:
+SELECT CONCAT(last_name,' earns ',TRUNCATE(salary,0),' monthly but wants ',TRUNCATE(salary*3,0)) "Dream Salary"
+FROM employees;
+
+#9、使用case-when,按照下面的条件:
+/*
+job				grade
+AD_PRES   A
+ST_MAN    B
+IT_PROG   C
+SA_REP    D
+ST_CLERK  E
+产生下面的结果
+*/
+
+SELECT last_name,job_id,CASE job_id 
+WHEN 'AD_PRES' THEN 'A'
+WHEN 'ST_MAN' THEN 'B'
+WHEN 'IT_PROG' THEN 'C'
+WHEN 'SA_REP' THEN 'D'
+WHEN 'ST_CLERK' THEN 'E'
+ELSE 'undefined' END "grade"
+FROM employees;
+
+
+
+

+ 362 - 0
第九章、子查询.sql

@@ -0,0 +1,362 @@
+#第九章、子查询
+
+#1、由一个具体的需求,引入子查询
+#需求:谁的工资比Abel的高?
+#方式一:
+SELECT last_name,salary
+FROM employees
+WHERE last_name = 'Abel';
+
+SELECT last_name,salary
+FROM employees
+WHERE salary > 11000;
+
+#方式二:自连接
+SELECT e2.last_name,e2.salary
+FROM employees e1,employees e2
+WHERE e2.salary > e1.salary	#多表的连接条件
+AND e1.last_name = 'Abel';
+
+#方式三:子查询
+SELECT last_name,salary
+FROM employees
+WHERE salary > (
+								SELECT salary
+								FROM employees
+								WHERE last_name = 'Abel'
+								);
+								
+#2、称谓的规范:外查询(或主查询)、内查询(或子查询)
+
+/*
+子查询(内查询)在主查询之前一次执行完成。
+子查询的结果被主查询(外查询)使用。
+
+注意事项:
+子查询要包含在括号内
+将子查询放在比较条件的右侧
+单行操作符对应单行子查询,多行操作符对应多行子查询
+*/
+/*
+3、子查询的分类
+角度1:从内查询返回的结果的条目数
+			单行子查询 vs 多行子查询
+角度2:内查询是否被执行多次
+			相关子查询 VS 不相关子查询
+比如:相关子查询的需求:查询工资大于本部门平均工资的员工信息
+			不相关子查询的需求:查询工资大于本公司平均工资的员工信息
+*/
+
+#子查询的编写技巧(或步骤):(1)、从里往外写	(2)、从外往里写
+
+#4、单行子查询
+#4.1、单行操作符: =	 !=	 >		>=		<		<=
+#题目1:查询工资大于149号员工工资的员工信息
+
+SELECT employee_id,last_name,salary
+FROM employees
+WHERE salary > (
+								SELECT salary
+								FROM employees
+								WHERE employee_id = 149
+								);
+
+#题目2:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
+
+SELECT last_name,job_id,salary
+FROM employees
+WHERE job_id = (
+								SELECT job_id
+								FROM employees
+								WHERE employee_id = 141
+								)
+AND salary > (
+								SELECT salary
+								FROM employees
+								WHERE employee_id = 143
+								);
+
+#题目3:返回公司工资最少的员工的last_name,job_id和salary。
+
+SELECT last_name,job_id,salary
+FROM employees
+WHERE salary = (
+								SELECT MIN(salary)
+								FROM employees
+								);
+								
+#题目4:查询与141号员工的manager_id和department_id相同的其他员工的employee_id,manager_id,department_id。
+
+#方式一:适用性更好
+SELECT employee_id,manager_id,department_id
+FROM employees
+WHERE manager_id = (
+										SELECT manager_id
+										FROM employees
+										WHERE employee_id = 141
+										)
+AND department_id = (
+										SELECT department_id
+										FROM employees
+										WHERE employee_id = 141
+										)
+AND employee_id <> 141;
+
+#方式二
+SELECT employee_id,manager_id,department_id
+FROM employees
+WHERE (manager_id,department_id)=(
+																	SELECT manager_id,department_id
+																	FROM employees
+																	WHERE employee_id = 141
+																	)
+AND employee_id <> 141;
+
+#题目5:查询最低工资大于110号部门最低工资的部门id和其最低工资
+
+SELECT department_id,MIN(salary)
+FROM employees
+WHERE department_id IS NOT NULL
+GROUP BY department_id
+HAVING MIN(salary) > (
+											SELECT MIN(salary)
+											FROM employees
+											WHERE department_id = 110
+											);
+
+#题目6:显示员工的employee_id,last_name和location。其中,若员工department_id与location_id为1800的department_id相同,则location为“Canada”,其余则为“USA”
+
+SELECT employee_id,last_name,
+CASE department_id WHEN (
+													SELECT department_id
+													FROM departments
+													WHERE location_id = 1800
+													) THEN 'Canada' 
+										ELSE 'USA' END "location"
+FROM employees;
+
+#4.2、子查询中的空值问题
+SELECT last_name,job_id
+FROM employees
+WHERE job_id = (
+								SELECT job_id
+								FROM employees
+								WHERE last_name = 'Haas'
+								);
+#4.3、非法使用子查询
+#错误:Subquery returns more than 1 row
+-- SELECT employee_id,last_name
+-- FROM employees
+-- WHERE salary = (
+-- 								SELECT MIN(salary)
+-- 								FROM employees
+-- 								GROUP BY department_id
+-- 								);
+
+#5、多行子查询
+#5.1、多行子查询的操作符:IN	ANY	ALL	SOME(同ANY)
+
+#5.2、举例
+# IN
+SELECT employee_id,last_name
+FROM employees
+WHERE salary IN (
+								SELECT MIN(salary)
+								FROM employees
+								GROUP BY department_id
+								);
+
+# ANY / ALL
+#题目:返回其他job_id中比job_id为IT_PROG部门任一工资低的员工的员工号、姓名、
+#job_id以及salary
+
+SELECT employee_id,last_name,job_id,salary
+FROM employees
+WHERE job_id <> 'IT_PROG'
+AND salary < ANY(
+									SELECT salary
+									FROM employees
+									WHERE job_id = 'IT_PROG'
+								);
+
+#题目:返回其他job_id中比job_id为IT_PROG部门所有工资低的员工的员工号、姓名、
+#job_id以及salary
+
+SELECT employee_id,last_name,job_id,salary
+FROM employees
+WHERE job_id <> 'IT_PROG'
+AND salary < ALL (
+									SELECT salary
+									FROM employees
+									WHERE job_id = 'IT_PROG'
+								);
+
+#题目:查询平均工资最低的部门id
+#MySQL中聚合函数是不能嵌套的
+#方式一:
+
+SELECT department_id
+FROM employees
+GROUP BY department_id
+HAVING AVG(salary) = (
+											SELECT MIN(avg_sal)
+											FROM (
+														SELECT AVG(salary) avg_sal
+														FROM employees
+														GROUP BY department_id
+														) t_dept_avg_sal
+											);
+
+#方式二:
+SELECT department_id
+FROM employees
+GROUP BY department_id
+HAVING AVG(salary) <= ALL (											
+											SELECT AVG(salary) avg_sal
+											FROM employees
+											GROUP BY department_id													
+											);
+
+#5.3、空值问题
+SELECT last_name
+FROM employees
+WHERE employee_id NOT IN (
+											SELECT manager_id
+											FROM employees
+											WHERE manager_id IS NOT NULL
+											);
+
+#6、相关子查询
+#6.1
+#回顾:查询员工中工资大于公司平均工资的员工的last_name,salary和其department_id
+SELECT last_name,salary,department_id
+FROM employees
+WHERE salary > (
+								SELECT AVG(salary)
+								FROM employees
+								);
+
+#题目2:查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id
+#方式一:使用相关子查询
+SELECT last_name,salary,department_id
+FROM employees e1
+WHERE salary > (
+								SELECT AVG(salary)
+								FROM employees e2
+								WHERE department_id = e1.department_id
+								);
+
+#方式二:在FROM中声明子查询
+
+SELECT e.last_name,e.salary,e.department_id
+FROM employees e,(
+								SELECT department_id,AVG(salary) avg_sal
+								FROM employees
+								GROUP BY department_id
+								) t_dept_avg_sal
+WHERE e.department_id = t_dept_avg_sal.department_id
+AND e.salary > t_dept_avg_sal.avg_sal;
+
+#题目:查询员工的id,salary,按照department_name排序
+
+SELECT employee_id,salary
+FROM employees e
+ORDER BY (
+					SELECT department_name
+					FROM departments d
+					WHERE e.department_id = d.department_id
+					) ASC;
+
+#结论:在SELECT中,除了GROUP BY和LIMIT之外,其他位置都可以声明子查询。
+
+#题目:若employees表中employee_id与job_history表中employee_id相同的数目
+#不小于2,输出这些相同id的员工的employee_id,last_name和job_id。
+
+SELECT * FROM job_history;
+
+SELECT employee_id,last_name,job_id
+FROM employees e
+WHERE 2 <=(
+						SELECT COUNT(*)
+						FROM job_history j
+						WHERE e.employee_id = j.employee_id
+					);
+
+#6.2、EXISTS与NOT EXISTS关键字
+#题目:查询公司管理者的employee_id,last_name,job_id,department_id信息
+#方式一:自连接
+
+SELECT DISTINCT mgr.employee_id,mgr.last_name,mgr.job_id,mgr.department_id
+FROM employees emp JOIN employees mgr
+ON emp.manager_id = mgr.employee_id;
+
+#方式二:子查询
+
+SELECT DISTINCT employee_id,last_name,job_id,department_id
+FROM employees emp
+WHERE employee_id IN (
+											SELECT DISTINCT manager_id
+											FROM employees
+											);
+
+#我做的
+SELECT employee_id,last_name,job_id,department_id
+FROM employees
+WHERE employee_id IN (
+										SELECT manager_id
+										FROM employees
+										WHERE manager_id IS NOT NULL
+										GROUP BY manager_id
+										);
+
+#方式三:EXISTS
+
+SELECT employee_id,last_name,job_id,department_id
+FROM employees e1
+WHERE EXISTS (
+							SELECT *
+							FROM employees e2
+							WHERE e1.employee_id = e2.manager_id
+							);
+
+#题目:查询departments表中,不存在与employees表中的部门的department_id和department_name。
+#方式一:外连接
+
+SELECT d.department_id,d.department_name
+FROM employees e RIGHT JOIN departments d
+ON e.department_id = d.department_id
+WHERE e.department_id IS NULL;
+
+#方式二:使用NOT EXISTS
+
+SELECT department_id,department_name
+FROM departments d
+WHERE NOT EXISTS (
+							SELECT *
+							FROM employees e
+							WHERE d.department_id = e.department_id
+							);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 652 - 0
第九章、练习题.sql

@@ -0,0 +1,652 @@
+#第九章、练习题
+
+#1、查询和Zlotkey相同部门的员工姓名和工资。
+SELECT last_name,salary
+FROM employees
+WHERE department_id IN (
+											SELECT department_id
+											FROM employees
+											WHERE last_name = 'Zlotkey'
+											);
+
+#2、查询工资比公司平均工资高的员工的员工号,姓名和工资。
+SELECT employee_id,last_name,salary
+FROM employees
+WHERE salary > (
+								SELECT AVG(salary)
+								FROM employees
+								);
+
+#3、选择工资大于所有JOB_ID = 'SA_MAN'的员工的工资的
+#员工的last_name,job_id,salary。
+
+SELECT last_name,job_id,salary
+FROM employees
+WHERE salary > ALL (
+										SELECT salary
+										FROM employees
+										WHERE job_id = 'SA_MAN'
+										);
+
+#4、查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名。
+SELECT employee_id,last_name
+FROM employees
+WHERE department_id IN (
+												SELECT department_id
+												FROM employees
+												WHERE last_name LIKE '%u%'
+												);
+#老师做的
+SELECT employee_id,last_name
+FROM employees
+WHERE department_id IN (
+												SELECT DISTINCT department_id
+												FROM employees
+												WHERE last_name LIKE '%u%'
+												);
+
+#5、查询在部门的location_id为1700的部门工作的员工的员工号。
+SELECT employee_id,last_name,department_id
+FROM employees
+WHERE department_id IN (
+												SELECT department_id
+												FROM departments
+												WHERE location_id = 1700
+												);
+
+#6、查询管理者是King的员工姓名和工资。
+SELECT e1.last_name,e1.salary,e1.manager_id
+FROM employees e1
+WHERE manager_id IN (
+											SELECT employee_id
+											FROM employees e2
+											WHERE last_name = 'King'
+										);
+
+#老师做的
+SELECT last_name,salary,manager_id
+FROM employees
+WHERE manager_id IN (
+											SELECT employee_id
+											FROM employees
+											WHERE last_name = 'King'
+										);
+#还可以用exists做
+
+#7、查询工资最低的员工信息:last_name,salary。
+SELECT last_name,salary
+FROM employees
+WHERE salary IN (
+								SELECT MIN(salary)
+								FROM employees
+								);
+
+#8、查询平均工资最低的部门信息。
+SELECT *
+FROM departments
+WHERE department_id = (SELECT department_id
+											FROM employees
+											GROUP BY department_id
+											HAVING AVG(salary) <= ALL(
+																								SELECT AVG(salary) avg_dsal
+																								FROM employees
+																								GROUP BY department_id
+																								)
+											);
+
+#老师做的
+#方式一
+SELECT *
+FROM departments
+WHERE department_id = (
+											SELECT department_id
+											FROM employees
+											GROUP BY department_id
+											HAVING AVG(salary) = (
+																						SELECT MIN(avg_sal)
+																						FROM (
+																									SELECT AVG(salary) avg_sal
+																									FROM employees
+																									GROUP BY department_id
+																									) t_dept_avg_sal
+																						)
+											);
+#方式二
+SELECT *
+FROM departments
+WHERE department_id = (
+											SELECT department_id
+											FROM employees
+											GROUP BY department_id
+											HAVING AVG(salary) <= ALL (
+																						SELECT AVG(salary)
+																						FROM employees
+																						GROUP BY department_id
+																						)
+											);
+
+#方式三:使用LIMIT
+SELECT *
+FROM departments
+WHERE department_id = (
+											SELECT department_id
+											FROM employees
+											GROUP BY department_id
+											HAVING AVG(salary) = (
+																						SELECT AVG(salary) avg_sal
+																						FROM employees
+																						GROUP BY department_id
+																						ORDER BY avg_sal
+																						LIMIT 0,1
+																						)
+											);
+#方式四
+SELECT d.*
+FROM departments d,(
+										SELECT department_id,AVG(salary) avg_sal
+										FROM employees
+										GROUP BY department_id
+										ORDER BY avg_sal ASC
+										LIMIT 0,1
+										) t_dept_avg_sal
+WHERE d.department_id = t_dept_avg_sal.department_id;
+
+
+#9、查询平均工资最低的部门信息和该部门的平均工资(相关子查询)。
+#我做的,差平均工资未做
+SELECT *
+FROM departments
+WHERE department_id = (
+												SELECT department_id
+												FROM employees
+												GROUP BY department_id
+												HAVING AVG(salary) <= ALL(
+																									SELECT AVG(salary)
+																									FROM employees
+																									GROUP BY department_id
+																									)
+												);
+
+#老师做的
+#方式一
+SELECT d.*,(SELECT AVG(salary) FROM employees WHERE department_id = d.department_id) AS d_avg_sal
+FROM departments d
+WHERE department_id = (
+											SELECT department_id
+											FROM employees
+											GROUP BY department_id
+											HAVING AVG(salary) = (
+																						SELECT MIN(avg_sal)
+																						FROM (
+																									SELECT AVG(salary) avg_sal
+																									FROM employees
+																									GROUP BY department_id
+																									) t_dept_avg_sal
+																						)
+											);
+
+#方式二
+SELECT d.*,(SELECT AVG(salary) FROM employees WHERE department_id = d.department_id) AS d_avg_sal
+FROM departments d
+WHERE department_id = (
+											SELECT department_id
+											FROM employees
+											GROUP BY department_id
+											HAVING AVG(salary) <= ALL (
+																						SELECT AVG(salary)
+																						FROM employees
+																						GROUP BY department_id
+																						)
+											);
+
+#方式三:使用LIMIT
+SELECT d.*,(SELECT AVG(salary) FROM employees WHERE department_id = d.department_id) AS d_avg_sal
+FROM departments d
+WHERE department_id = (
+											SELECT department_id
+											FROM employees
+											GROUP BY department_id
+											HAVING AVG(salary) = (
+																						SELECT AVG(salary) avg_sal
+																						FROM employees
+																						GROUP BY department_id
+																						ORDER BY avg_sal
+																						LIMIT 0,1
+																						)
+											);
+#方式四
+SELECT d.*,(SELECT AVG(salary) FROM employees WHERE department_id = d.department_id) AS d_avg_sal
+FROM departments d,(
+										SELECT department_id,AVG(salary) avg_sal
+										FROM employees
+										GROUP BY department_id
+										ORDER BY avg_sal ASC
+										LIMIT 0,1
+										) t_dept_avg_sal
+WHERE d.department_id = t_dept_avg_sal.department_id;
+
+#10、查询平均工资最高的job信息。
+
+SELECT *
+FROM jobs
+WHERE job_id = (SELECT job_id
+								FROM employees
+								GROUP BY job_id
+								HAVING AVG(salary) >= ALL(
+																					SELECT AVG(salary)
+																					FROM employees
+																					GROUP BY job_id
+																					)
+								);
+
+#老师做的
+#方式一:
+SELECT *
+FROM jobs
+WHERE job_id = (
+								SELECT job_id
+								FROM employees
+								GROUP BY job_id
+								HAVING AVG(salary) = (
+																			SELECT MAX(avg_sal)
+																			FROM (
+																						SELECT AVG(salary) avg_sal
+																						FROM employees
+																						GROUP BY job_id
+																						) t_dept_avg_sal
+																			)
+								);
+
+#方式二
+SELECT *
+FROM jobs
+WHERE job_id = (
+								SELECT job_id
+								FROM employees
+								GROUP BY job_id
+								HAVING AVG(salary) >= ALL (
+																			SELECT AVG(salary)
+																			FROM employees
+																			GROUP BY job_id
+																			)
+								);
+
+#方式三
+SELECT *
+FROM jobs
+WHERE job_id = (
+								SELECT job_id
+								FROM employees
+								GROUP BY job_id
+								HAVING AVG(salary) =  (
+																			SELECT AVG(salary) avg_sal
+																			FROM employees
+																			GROUP BY job_id
+																			ORDER BY avg_sal DESC
+																			LIMIT 0,1
+																			)
+								);
+
+#方式四
+
+SELECT j.*
+FROM jobs j,(
+							SELECT job_id,AVG(salary) avg_sal
+							FROM employees
+							GROUP BY job_id
+							ORDER BY avg_sal DESC
+							LIMIT 0,1
+							) t_dept_avg_sal
+WHERE j.job_id = t_dept_avg_sal.job_id;
+
+#11、查询平均工资高于公司平均工资的部门有哪些?
+#我做的,不对
+SELECT department_id
+FROM employees
+GROUP BY department_id
+HAVING (
+				SELECT AVG(salary)
+				FROM employees
+				) < ANY (
+							SELECT AVG(salary)
+							FROM employees
+							GROUP BY department_id
+							)
+
+#老师做的
+SELECT department_id
+FROM employees
+WHERE department_id IS NOT NULL
+GROUP BY department_id
+HAVING AVG(salary) > (
+											SELECT AVG(salary)
+											FROM employees
+											);
+
+#12、查询出公司中所有manager的详细信息。
+
+SELECT *
+FROM employees
+WHERE employee_id IN (
+											SELECT manager_id
+											FROM employees
+											GROUP BY manager_id
+											);
+
+#老师做的(讲EXISTS时的练习题)
+#方式一:自连接
+SELECT DISTINCT mgr.employee_id,mgr.last_name,mgr.job_id,mgr.department_id
+FROM employees emp JOIN employees mgr
+ON emp.manager_id = mgr.employee_id;
+
+#方式二:子查询
+SELECT DISTINCT employee_id,last_name,job_id,department_id
+FROM employees emp
+WHERE employee_id IN (
+											SELECT DISTINCT manager_id
+											FROM employees
+											);
+
+#方式三:EXISTS
+SELECT employee_id,last_name,job_id,department_id
+FROM employees e1
+WHERE EXISTS (
+							SELECT *
+							FROM employees e2
+							WHERE e1.employee_id = e2.manager_id
+							);
+
+#13、各个部门中,最高工资中最低的那个部门的最低工资是多少?
+
+#我做的,不对
+SELECT MIN(salary)
+FROM employees
+WHERE department_id = (
+												SELECT department_id
+												FROM (
+															SELECT MAX(salary),department_id
+															FROM employees
+															) d_max
+											);
+
+#老师做的
+#方式一
+SELECT MIN(salary)
+FROM employees
+WHERE department_id = (
+												SELECT department_id
+												FROM employees
+												GROUP BY department_id
+												HAVING MAX(salary) = (
+																							SELECT MIN(max_sal)
+																							FROM(
+																									SELECT MAX(salary) max_sal
+																									FROM employees
+																									GROUP BY department_id
+																									) t_dept_max_sal
+																							)
+												);
+
+#方式二
+SELECT MIN(salary)
+FROM employees
+WHERE department_id = (
+												SELECT department_id
+												FROM employees
+												GROUP BY department_id
+												HAVING MAX(salary) <= ALL (
+																								SELECT MAX(salary)
+																								FROM employees
+																								GROUP BY department_id
+																							)
+												);
+
+#方式三
+SELECT MIN(salary)
+FROM employees
+WHERE department_id = (
+												SELECT department_id
+												FROM employees
+												GROUP BY department_id
+												HAVING MAX(salary) = (
+																								SELECT MAX(salary) max_sal
+																								FROM employees
+																								GROUP BY department_id
+																								ORDER BY max_sal ASC
+																								LIMIT 0,1
+																							)
+												);
+
+#方式四
+SELECT MIN(salary)
+FROM employees e,(
+									SELECT department_id,MAX(salary) max_sal
+									FROM employees
+									GROUP BY department_id
+									ORDER BY max_sal ASC
+									LIMIT 0,1
+									) t_dept_max_sal
+WHERE e.department_id = t_dept_max_sal.department_id;
+
+#14、查询平均工资最高的部门的manager的详细信息:
+# last_name,department_id,email,salary
+
+SELECT last_name,department_id,email,salary
+FROM employees
+WHERE employee_id IN (
+											SELECT DISTINCT manager_id
+											FROM employees
+											WHERE department_id = (SELECT department_id
+																						FROM employees
+																						GROUP BY department_id
+																						HAVING AVG(salary) >= ALL (
+																																			SELECT AVG(salary)
+																																			FROM employees
+																																			GROUP BY department_id
+																																			)
+																							)
+											)
+
+#老师做的
+#方式一
+SELECT last_name,department_id,email,salary
+FROM employees
+WHERE employee_id IN (
+											SELECT DISTINCT manager_id
+											FROM employees
+											WHERE department_id = (
+																							SELECT department_id
+																							FROM employees
+																							GROUP BY department_id
+																							HAVING AVG(salary) = (
+																																		SELECT MAX(avg_sal)
+																																		FROM(
+																																					SELECT AVG(salary) avg_sal
+																																					FROM employees
+																																					GROUP BY department_id
+																																					) t_dept_avg_sal
+																																		)
+																							)
+											);
+
+#方式二
+SELECT last_name,department_id,email,salary
+FROM employees
+WHERE employee_id IN (
+											SELECT DISTINCT manager_id
+											FROM employees
+											WHERE department_id = (
+																							SELECT department_id
+																							FROM employees
+																							GROUP BY department_id
+																							HAVING AVG(salary) >= ALL (
+																																		SELECT AVG(salary)
+																																		FROM employees
+																																		GROUP BY department_id
+																																		)
+																							)
+											);
+
+#方式三
+SELECT last_name,department_id,email,salary
+FROM employees
+WHERE employee_id IN (
+											SELECT DISTINCT manager_id
+											FROM employees e,(
+																				SELECT department_id,AVG(salary) avg_sal
+																				FROM employees
+																				GROUP BY department_id
+																				ORDER BY avg_sal DESC
+																				LIMIT 0,1
+																				) t_dept_avg_sal
+											WHERE e.department_id = t_dept_avg_sal.department_id
+											);
+
+
+#15、查询部门的部门号,其中不包括job_id是“ST_CLERK"的部门号。
+#我做的也对,只是使用的表是employees,换成departments表就和老师做的结果一样
+SELECT DISTINCT department_id
+FROM employees
+WHERE department_id <> (
+												SELECT department_id
+												FROM employees
+												WHERE job_id = 'ST_CLERK'
+												GROUP BY job_id
+												);
+
+#老师做的
+#方式一
+SELECT department_id
+FROM departments
+WHERE department_id NOT IN (
+														SELECT DISTINCT department_id
+														FROM employees
+														WHERE job_id = 'ST_CLERK'
+														);
+
+#方式二
+SELECT department_id
+FROM departments d
+WHERE NOT EXISTS(
+							SELECT *
+							FROM employees e
+							WHERE d.department_id = e.department_id
+							AND e.job_id = 'ST_CLERK'
+							);
+							
+
+#16、选择所有没有管理者的员工的last_name。
+#我做的,所得结果与老师的代码一致
+SELECT last_name
+FROM employees
+WHERE manager_id IS NULL;
+
+#老师做的
+SELECT emp.last_name
+FROM employees emp
+WHERE NOT EXISTS (
+							SELECT *
+							FROM employees mgr
+							WHERE emp.manager_id = mgr.employee_id
+							);
+
+
+#17、查询员工号、姓名、雇佣时间、工资,其中员工的管理者为“De Haan”。
+SELECT employee_id,last_name,hire_date,salary
+FROM employees
+WHERE manager_id = (
+										SELECT employee_id
+										FROM employees
+										WHERE last_name = 'De Haan'
+										);
+
+#老师做的
+#方式一
+SELECT employee_id,last_name,hire_date,salary
+FROM employees
+WHERE manager_id IN (
+										SELECT employee_id
+										FROM employees
+										WHERE last_name = 'De Haan'
+										);
+
+#方式二
+SELECT e1.employee_id,e1.last_name,e1.hire_date,e1.salary
+FROM employees e1
+WHERE EXISTS (
+							SELECT *
+							FROM employees e2
+							WHERE e1.manager_id = e2.employee_id
+							AND e2.last_name = 'De Haan'
+							);
+
+
+#18、查询各部门中工资比本部门平均工资高的员工的员工号,姓名和工资(相关子查询)
+
+#在相关子查询课程中已作为例题讲解
+#方式一:使用相关子查询
+SELECT last_name,salary,department_id
+FROM employees e1
+WHERE salary > (
+								SELECT AVG(salary)
+								FROM employees e2
+								WHERE department_id = e1.department_id
+								);
+
+#方式二:在FROM中声明子查询
+
+SELECT e.last_name,e.salary,e.department_id
+FROM employees e,(
+								SELECT department_id,AVG(salary) avg_sal
+								FROM employees
+								GROUP BY department_id
+								) t_dept_avg_sal
+WHERE e.department_id = t_dept_avg_sal.department_id
+AND e.salary > t_dept_avg_sal.avg_sal;
+
+
+#19、查询每个部门下的部门人数大于5的部门名称(相关子查询)
+SELECT d.department_name
+FROM departments d
+WHERE 5 < (
+					SELECT COUNT(*)
+					FROM employees e
+					WHERE e.department_id = d.department_id
+					);
+
+#20、查询每个国家下的部门个数大于2的国家编号(相关子查询)
+SELECT * FROM locations
+
+SELECT country_id
+FROM locations l
+WHERE 2 < (
+					SELECT COUNT(*)
+					FROM departments d
+					WHERE l.location_id = d.location_id
+					);
+
+/*
+子查询的编写技巧(或步骤):(1)、从里往外写		(2)、从外往里写
+如何选择?
+1、如果子查询相对较简单,建议从外往里写。一旦子查询结构较复杂,则建议从里往外写。
+2、如果是相关子查询,通常都是从外往里写。
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 133 - 0
第九章、练习题二(单独自己写).sql

@@ -0,0 +1,133 @@
+#第九章、练习题二(单独自己写)
+
+#错题及未做的题:9(还是不熟)、11(还是不熟)、13(还是不熟)、18、19、20
+
+#1、查询和Zlotkey相同部门的员工姓名和工资。
+
+
+#2、查询工资比公司平均工资高的员工的员工号,姓名和工资。
+
+#3、选择工资大于所有JOB_ID = 'SA_MAN'的员工的工资的
+#员工的last_name,job_id,salary。
+
+
+
+#4、查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名。
+
+
+#5、查询在部门的location_id为1700的部门工作的员工的员工号。
+
+#6、查询管理者是King的员工姓名和工资。
+
+
+#7、查询工资最低的员工信息:last_name,salary。
+
+#8、查询平均工资最低的部门信息。
+
+
+#9、查询平均工资最低的部门信息和该部门的平均工资(相关子查询)。
+# 还是不熟
+SELECT d.*,(SELECT AVG(salary) FROM employees WHERE department_id = d.department_id)
+FROM departments d
+WHERE department_id = (
+												SELECT department_id
+												FROM employees
+												GROUP BY department_id
+												HAVING AVG(salary) <= ALL (
+																										SELECT AVG(salary)
+																										FROM employees
+																										GROUP BY department_id
+																										)
+												);
+
+
+
+								
+#10、查询平均工资最高的job信息。
+
+
+
+#11、查询平均工资高于公司平均工资的部门有哪些?
+SELECT department_id
+FROM employees
+WHERE department_id IS NOT NULL
+GROUP BY department_id
+HAVING AVG(salary) > (
+											SELECT AVG(salary)
+											FROM employees
+											)
+
+
+#12、查询出公司中所有manager的详细信息。
+
+
+
+#13、各个部门中,最高工资中最低的那个部门的最低工资是多少?
+SELECT MIN(salary)
+FROM employees
+WHERE department_id IN (
+												SELECT department_id
+												FROM employees
+												GROUP BY department_id
+												HAVING MAX(salary) <= ALL (
+																										SELECT MAX(salary)
+																										FROM employees
+																										GROUP BY department_id
+																										)
+												)
+
+
+#14、查询平均工资最高的部门的manager的详细信息:
+# last_name,department_id,email,salary
+
+
+
+#15、查询部门的部门号,其中不包括job_id是“ST_CLERK"的部门号。
+
+
+#16、选择所有没有管理者的员工的last_name。
+
+
+
+#17、查询员工号、姓名、雇佣时间、工资,其中员工的管理者为“De Haan”。
+
+
+
+#18、查询各部门中工资比本部门平均工资高的员工的员工号,姓名和工资(相关子查询)
+
+
+#19、查询每个部门下的部门人数大于5的部门名称(相关子查询)
+
+
+#20、查询每个国家下的部门个数大于2的国家编号(相关子查询)
+SELECT * FROM locations
+
+SELECT country_id
+FROM locations l
+WHERE 2 < (
+						SELECT COUNT(*)
+						FROM departments d
+						WHERE l.location_id = d.location_id
+						)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 81 - 0
第八章、练习题.sql

@@ -0,0 +1,81 @@
+#第八章、练习题
+
+#1、WHERE子句可否使用组函数进行过滤?
+#不能
+
+#2、查询公司员工工资的最大值,最小值,平均值,总和
+SELECT MAX(salary) max_sal,MIN(salary) min_sal,AVG(salary) avg_sal,SUM(salary) sum_sal
+FROM employees;
+
+#3、查询各job_id的员工工资的最大值,最小值,平均值,总和
+SELECT job_id,MAX(salary) max_sal,MIN(salary) min_sal,AVG(salary) avg_sal,SUM(salary) sum_sal
+FROM employees
+GROUP BY job_id;
+
+#4、选择具有各个job_id的员工人数
+SELECT job_id,COUNT(job_id)
+FROM employees
+GROUP BY job_id;
+
+#老师做的
+SELECT job_id,COUNT(*)
+FROM employees
+GROUP BY job_id;
+
+#5、查询员工最高工资和最低工资的差距(DIFFERENCE)
+SELECT MAX(salary)-MIN(salary) AS DIFFERENCE
+FROM employees;
+
+#6、查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内
+#我做的,不对
+SELECT mgr.last_name,COUNT(emp.last_name),MIN(emp.salary)
+FROM employees mgr JOIN employees emp
+ON emp.employee_id = mgr.manager_id
+GROUP BY mgr.manager_id
+HAVING MIN(emp.salary) > 6000;
+
+#老师做的
+SELECT manager_id,MIN(salary)
+FROM employees
+WHERE manager_id IS NOT NULL
+GROUP BY manager_id
+HAVING MIN(salary) >= 6000;
+
+
+#7、查询所有部门的名字,location_id,员工数量和平均工资,并按平均工资降序
+SELECT DISTINCT e.department_id,d.department_name,d.location_id,COUNT(last_name),AVG(salary)
+FROM employees e,departments d
+WHERE e.department_id = d.department_id
+GROUP BY e.department_id
+ORDER BY AVG(salary) DESC;
+
+#老师做的
+SELECT d.department_name,d.location_id,COUNT(employee_id),AVG(salary)
+FROM departments d LEFT JOIN employees e
+ON d.department_id = e.department_id
+GROUP BY department_name,location_id
+ORDER BY AVG(salary) DESC;
+
+-- SELECT e.employee_id,salary,d.department_name,d.location_id
+-- FROM employees e RIGHT JOIN departments d
+-- ON e.department_id = d.department_id;
+
+
+#8、查询每个工种、每个部门的部门名、工种名和最低工资
+SELECT e.department_id,d.department_name,e.job_id,MIN(e.salary)
+FROM employees e RIGHT JOIN departments d
+ON e.department_id = d.department_id
+GROUP BY department_id,job_id
+
+#老师做的
+SELECT d.department_name,e.job_id,MIN(salary)
+FROM departments d LEFT JOIN employees e
+ON e.department_id = d.department_id
+GROUP BY department_name,job_id
+
+
+
+
+
+
+

+ 194 - 0
第八章、聚合函数.sql

@@ -0,0 +1,194 @@
+#第八章、聚合函数
+
+#1、常见的几个聚合函数
+#1.1、AVG/SUM:只适用于数值类型的字段(或变量)
+SELECT AVG(salary),SUM(salary),AVG(salary)*107
+FROM employees;
+
+#如下的操作没有意义
+SELECT SUM(last_name),AVG(last_name),SUM(hire_date)
+FROM employees;
+
+#1.2、MAX/MIN:适用于数值类型、字符串类型、日期和时间类型的字段(或变量)
+SELECT MAX(salary),MIN(salary)
+FROM employees;
+
+SELECT MAX(last_name),MIN(last_name),MAX(hire_date),MIN(hire_date)
+FROM employees;
+
+#1.3、COUNT
+#(1)、作用:计算指定字段在查询结果中出现的个数(不包含NULL值的)
+SELECT COUNT(employee_id),COUNT(salary),COUNT(2*salary),COUNT(1),COUNT(2),COUNT(*)
+FROM employees;
+
+#如果计算表中有多少条记录,如何实现?
+#方式1:COUNT(*)
+#方式2:COUNT(1),即COUNT(常数)
+#方式3:COUNT(具体字段):不一定对!所以使用的时候要注意,尽量避免使用
+
+#(2)注意:计算指定字段出现的个数时,是不计算NULL值的。
+SELECT COUNT(commission_pct)
+FROM employees;
+
+SELECT commission_pct
+FROM employees
+WHERE commission_pct IS NOT NULL;
+
+#(3)、公式:AVG = SUM / COUNT
+SELECT AVG(salary),SUM(salary)/COUNT(salary),
+AVG(commission_pct),SUM(commission_pct)/COUNT(commission_pct),
+SUM(commission_pct)/107
+FROM employees;
+
+#需求:查询公司中平均奖金率
+#错误的
+SELECT AVG(commission_pct)
+FROM employees;
+
+#正确的
+SELECT SUM(commission_pct) / COUNT(IFNULL(commission_pct,0)),
+AVG(IFNULL(commission_pct,0))
+FROM employees;
+
+#如果需要统计表中的记录数,使用COUNT(*)、COUNT(1)、COUNT(具体字段)哪个效率更高呢?
+#如果使用的是MyISAM存储引擎,则三者效率相同都是O(1)
+#如果使用的是InnoDB存储引擎,则三者效率COUNT(*)=COUNT(1)>COUNT(具体字段)
+
+#其它:方差、标准差、中位数
+
+#2、GROUP BY的使用
+
+#需求:查询各个部门的平均工资
+SELECT department_id,AVG(salary),SUM(salary)
+FROM employees
+GROUP BY department_id;
+
+#需求:查询各个jos_id的平均工资
+SELECT job_id,AVG(salary)
+FROM employees
+GROUP BY job_id;
+
+#需求:查询各个department_id,job_id的平均工资
+#方式一:
+SELECT department_id,job_id,AVG(salary)
+FROM employees
+GROUP BY department_id,job_id;
+#方式二
+SELECT job_id,department_id,AVG(salary)
+FROM employees
+GROUP BY job_id,department_id;
+
+#错误的
+SELECT department_id,job_id,AVG(salary)
+FROM employees
+GROUP BY department_id;
+
+#结论1:SELECT中出现的非组函数的字段必须声明在GROUP BY中,反之,GROUP BY中声明的字段可以不出现在SELECT中。
+#结论2:GROUP BY声明在FROM后面、WHERE后面,ORDER BY前面、LIMIT前面。
+#结论3:MySQL中GROUP BY中使用WITH ROLLUP
+SELECT department_id,AVG(salary)
+FROM employees
+GROUP BY department_id WITH ROLLUP;
+
+#需求:查询各个部门的平均工资,按照平均工资升序排列
+SELECT department_id,AVG(salary) AS avg_sal
+FROM employees
+GROUP BY department_id
+ORDER BY avg_sal ASC;
+
+#说明:当使用ROLLUP时,不能同时使用ORDER BY子句进行结果排序,即ROLLUP和ORDER BY是互相排斥的
+#错误的
+SELECT department_id,AVG(salary) AS avg_sal
+FROM employees
+GROUP BY department_id WITH ROLLUP
+ORDER BY avg_sal ASC;
+
+
+#3、HAVING的使用(作用:用来过滤数据的)
+#练习:查询各个部门中最高工资比10000高的部门信息
+#错误的写法:
+SELECT department_id,MAX(salary)
+FROM employees
+WHERE MAX(salary) > 10000
+GROUP BY department_id;
+
+#要求1:如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE,否则,报错
+#要求2:HAVING必须声明在GROUP BY的后面。
+#正确的写法:
+SELECT department_id,MAX(salary)
+FROM employees
+GROUP BY department_id
+HAVING MAX(salary) > 10000;
+
+#要求3:开发中,我们使用HAVING的前提是SQL中使用了GROUP BY。
+
+#练习:查询部门id为10,20,30,40这4个部门中最高工资比10000高的部门信息
+#方式一:推荐,执行效率高于方式二
+SELECT department_id,MAX(salary)
+FROM employees
+WHERE department_id IN (10,20,30,40)
+GROUP BY department_id
+HAVING MAX(salary) > 10000;
+
+#方式二
+SELECT department_id,MAX(salary)
+FROM employees
+GROUP BY department_id
+HAVING MAX(salary) > 10000 AND department_id IN (10,20,30,40);
+
+#结论:当过滤条件中有聚合函数时,则此过滤条件必须声明在HAVING中
+#当过滤条件中没有聚合函数时,则此过滤条件声明在WHERE中或HAVING中都可以。但是建议声明在WHERE中。
+
+/*
+WHERE与HAVING对比
+1、从适用范围上来讲,HAVING的适用范围更广。
+2、如果过滤条件中没有聚合函数:这种情况下,WHERE的执行效率要高于HAVING。
+*/
+
+#4、SQL底层执行原理
+#4.1、SELECT语句的完整结构
+/*
+#SQL92语法:
+SELECT ……,……,……(存在聚合函数)
+FROM ……,……,……
+WHERE 多表的连接条件 AND 不包含聚合函数的过滤条件
+GROUP BY ……,……
+HAVING 包含聚合函数的过滤条件
+ORDER BY ……,……(ASC / DESC)
+LIMIT……,……
+
+#SQL99语法:
+SELECT ……,……,……(存在聚合函数)
+FROM …… (LEFT / RIGHT)JOIN …… ON 多表的连接条件
+(LEFT / RIGHT)JOIN …… ON ……
+WHERE 不包含聚合函数的过滤条件
+GROUP BY ……,……
+HAVING 包含聚合函数的过滤条件
+ORDER BY ……,……(ASC / DESC)
+LIMIT……,……
+*/
+
+#4.2、SQL语句的执行过程
+#FROM ……,…… -->ON -->(LEFT / RIGHT)JOIN --> WHERE --> GROUP BY --> HAVING -->SELECT --> DISTINCT --> ORDER BY --> LIMIT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+