数据库第二天
第一天补充
ifnull函数
功能:判断某字段或表达式是否为null,如果为null 返回指定值 否则返回原本的值
isnull函数
功能:判断某字段或表达式是否为null,如果是则返回1 不是则返回0
进阶三:排序查询
引入
SELECT * FROM employees;
语法:
SELECT 查询列表
FROM 表
WHERE 筛选条件
ORDER BY 排序列表 【desc|aesc】#desc从高到低 aesc从低到高
特点:
1.asc代表升序 desc是降序 如果不写,默认是升序
2.ORDER BY子句中可以支持单个字段,多个字段,表达式,函数,别名
3.ORDER BY 子句一般是放在查询语句的最后面,但limit子句除外
案例1:查询员工信息,按工资要求从高到低
SELECT * FROM employees ORDER BY salary desc;
SELECT * FROM employees ORDER BY salary;
案列2:查询部门编号>=90的员工信息,按入职时间先后进行排序 添加筛选条件
SELECT * FROM employees
WHERE department_id>=90
ORDER BY hiredate ASC;
案例3:按年龄的高低显示员工的信息和 年龄 按表达式排序顺序
SELECT * ,salary*12*(1+IFNULL(commission_pcT,0)) 年薪
FROM employees
ORDER BY salary*12*(1+IFNULL(commission_pcT,0)) DESC;
案例4:按年薪的高低显示员工的信息和年薪 按别名排序
SELECT * ,salary*12*(1+IFNULL(commission_pcT,0)) 年薪
FROM employees
ORDER BY 年薪 DESC;
案例5:按姓名的长度显示员工的姓名和工资 按函数排序
SELECT LENGTH(last_name) 字节长度,last_name,salary;
FROM employees
ORDER BY LENGTH(last_name);
案例6:查询员工信息 要求按工资排序,再按员工编号排序(按多个字段排序)
SELECT*
FROM employees
ORDER BY salary ASC,employee_id DESC;
进阶四:常见函数
功能:类似于java的方法,将一组逻辑语句封装在方法体中,对外方便暴露方法名
好处:1.隐藏了实现细节 2.提高了代码的可读性
调用:SELECT 函数名(实参列表)|【from 表】;
特点:1.叫什么(函数名)
2.干什么(函数功能)
分类:
1.单行函数
如 concat,length,ifnull等
2.分组函数
功能:做统计使用,又称为统计函数,聚合函数,组函数
常见函数:
一、单行函数
字符函数:
length
concat
substr
instr
trim
upper
lower
lpad
rpad
replace
数学函数:
round
ceil
floor
truncate
mod
日期函数:
now
curdate
curtime
year
month
monthname
day
hour
minute
second
str_to_date
date_format
其他函数:
version
database
user
控制函数
if
case
二、分组函数
一、字符函数
1、length获取参数值的字节个数
SELECT LENGTH('join');
SELECT LENGTH('张三丰hahaha');
SHOW VARIABLES LIKE '%char%'
2.concat拼接字符串
SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;
3.upper、lower 大写变小写 小写改大写
SELECT UPPER('join')
SELECT LOWER('joIn')
将姓变大写,名变小写 然后拼接
SELECT CONCAT(UPPER(last_name),LOWER(first_name)) 姓名 FROM employees;
4.substring、substr
注意:索引从1开始
截取从指定索引处后面所有字符
SELECT SUBSTR('李莫愁爱上了路站元',6) out_put;
截取从指定索引处指定字符长度的字符
SELECT SUBSTR('李莫愁爱上了路站元',1,3) out_put;
案列:姓名中首字符大写,其他字符小写然后用_进行拼接,显示出来
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2)) out_put;
FROM employees;
5.instr 返回子串第一次出现的索引 如果找不到 则返回0
SELECT INSTR('杨不悔爱上了殷六侠','殷六侠') AS out_put;
6.trim
SELECT LENGTH(TRIM(' 张翠山 ')) AS out_put;
SELECT TRIM('a' FROM 'aaaaaaaaaaaaaa张aaaaaaaa翠山aaaaaaaaa') AS out_put;
7.lpad用指定的字符来左填充指定的长度
SELECT LPAD('殷素素',10,'*') AS out_put;
8.rpad用指定的字符来右填充指定的长度
SELECT RPAD('殷素素',10,'*') AS out_put;
9.replace 替换
SELECT REPLACE('周芷若周主任周主任周主任周主任周主任周主任','周主任','张三') AS out_put;
二、数学函数
round 四舍五入
SELECT ROUND(1.55);
SELECT ROUND(1.567,2);#小数点后面保留两位
ceil 向上取整 返回>=该整数的最小整数
SELECT CEIL(1.00)
floor 向下取整 返回<=该整数的最大整数
SELECT FLOOR(-9.9);
truncate 截断
SELECT TRUNCATE(1.65,1);
mod 取余
MOD(a,b):a-a/b*b;
SELECT MOD(10,3);
三、日期函数
now 返回当前系统日期+时间
SELECT NOW()
curdate 返回当前系统日期 不包含时间
SELECT CURDATE();
curtime 返回当前时间,不包含日期
SELECT CURTIME();
可以获取指定的部分,年月日小时分钟秒
SELECT YEAR(NOW()) 年;
SELECT YEAR('1998-1-1') 年;
SELECT YEAR(hiredate) 年 FROM employees;
SELECT MONTH(NOW()) 月;
SELECT MONTHTIME(NOW()) 月;
str_to_date:将日期格式的字符转换成指定格式的日期
STR_TO_DATE('9-13-1999','%m-%d-%Y')
date_format:将日期转换成字符串
DATE_FORMAT('2018/6/6','%Y年%m月%d日');
查询日期为1992-5-3的员工信息
SELECT * FROM employees WHERE hiredate='1992-5-3';
查询又奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %Y年') 入职日期
FROM employees;
WHERE commission_pcT IS NOT NULL;
四、其他函数
SELECT VERSION();
SELECT DATEBASE();
SELECT USER();
五、流程控制函数
1.if函数: if else 的效果
SELECT IF('10>5','大','小');
2.case函数使用一:switch case 的效果
case要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量1 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
案例:查询员工的工资,要求
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
其他部门,显示的工资为原工资
SELECT salary 原始工资,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
else salary
end AS 新工资
FROM employees
3.case函数的使用二:类似于 多重if
case
when 条件1 then 要显示的值1或语句1
when 条件1 then 要显示的值1或语句1
...
else 要显示的值n或语句n
end
案例:查询员工的工资情况
如果工资大于20000 显示A级别
如果工资大于15000 显示B级别
如果工资大于10000 显示C级别
否则 显示D级别
SELECT salary
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END AS 工资级别
FROM employees
二、分组函数
功能:做统计使用,又称为统计函数,聚合函数,组函数
分类:
sum 求和、avg求平均、max最大值 min最小值 count计算个数
特点:
1.sum,avg一般用于处理数值类型
max、min、count可以用于处理任何类型
2.以上分组函数忽略null值
3.可以和distinct搭配使用
4.count函数的单独介绍
一般用count(*) 来统计行数
5.和分组函数一同查询的字段要求是group by后的字段 其他的都不行
1.简单的使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT COUNT(salary) FROM employees;
SELECT SUM(salary) 和 , AVG(salary) 平均 , MIN(salary) 最小 , MAX(salary) 最大 , COUNT(salary) 个数
FROM employees;
SELECT SUM(salary) 和 ,ROUND(AVG(salary),2) 平均 , MIN(salary) 最小 , MAX(salary) 最大 , COUNT(salary) 个数
FROM employees;
2、参数支持哪些类型
SELECT SUM(last_name) ,AVG(last_name) FROM employees;
SELECT SUM(hiredate) ,AVG(hiredate) FROM employees;
SELECT MAX(last_name) ,MIN(last_name) FROM employees;
SELECT MAX(hiredate) ,MIN(hiredate) FROM employees;
SELECT COUNT(last_name) FROM employees;
SELECT COUNT(commission_pcT) FROM employees;
3.忽略null
SELECT SUM(commission_pcT) ,AVG (commission_pcT) FROM employees;
SELECT MIN(commission_pcT) ,MIN (commission_pcT) FROM employees;
SELECT COUNT(commission_pcT) FROM employees;
4.和distinct搭配
SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;
5.count函数的详细介绍
SELECT COUNT(salary ) FROM employees;
SELECT COUNT(*) FROM employees;
SELECT COUNT(1) FROM employees;
SELECT COUNT('字段') FROM employees;
效率:
MYISAM存储引擎下,COUNT(*) 的效率高
INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
6.和分组函数一同查询的字段有限制
SELECT AVG(salary),employee_id FROM employees;
求两个时间点相差的天数
SELECT DATEDIFF(NOW(),'1998-8-31')
进阶5:分组查询
语法:
select 分组函数,列(要求出现在group by的后面)
from 表
【where 筛选条件】
group by 分组的列表
【order by子句】
注意:
查询列表比较特殊:要求是分组函数和group by后出现的字段
特点:
1.分组查询中的筛选条件分为两类
数据源 位置 关键字
分组前筛选 原始表 group by前面 where
分组后筛选 分组后的结果集 group by后面 having
分组函数做条件肯定是放在having子句中
能用分组前筛选的 就优先考虑分组前筛选
2.group by子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开没有顺序要求),表达式或函数(用的较少)
3.可以添加排序(排序放在整个分组查询之后)
引入:查询每个部门的平均工资
SELECT AVG(salary) FROM employees;
简单的分组查询:
案列1:查询每个工种的最高工资
SELECT MAX(salary),job_id
FROM employees
group by job_id;
案例2:查询每个位置上的部门个数
SELECT COUNT(*),location_id
FROM departments
GROUP BY location_id;
添加筛选条件
案例1:查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;
案例2:查询有奖金的每个领导手下员工的最高工资
SELECT MAX(salary),manager_id
FROM employees
WHERE commission_pcT IS NOT NULL
GROUP BY manager_id;
添加分组后的筛选条件
案例1:查询哪个部门的员工数>2
1.查询每个部门的员工个数
SELECT count(*),department_id
FROM employees
GROUP BY department_id;
2.根据1的结果进行筛选,查询哪个部门的员工个数>2
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2
案例2:每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
1.查询每个工种有奖金的员工的最高工资
SELECT MAX(salary),job_id
FROM employees
WHERE commission_pcT IS NOT NULL
GROUP BY job_id;
2.根据1的结果进行筛选,最高工资>12000
SELECT MAX(salary),job_id
FROM employees
WHERE commission_pcT IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000;
案列3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资
1.查询每个领导手下的员工固定最低工资
SELECT MIN(salary),manager_id
FROM employees
GROUP BY manager_id
2.添加筛选条件:编号>102 最低工资大于5000
SELECT MIN(salary),manager_id
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING MIN(salary)>5000;
按表达式或函数分组
案例:按员工姓名的长度分钟,查询每一组的员工数,筛选员工个数>5的有哪些
1.查询每个长度的员工个数
SELECT COUNT(*),LENGTH(last_name) len_name
FROM employees
GROUP BY LENGTH(last_name);
2.添加筛选条件
SELECT COUNT(*),LENGTH(last_name) len_name
FROM employees
GROUP BY LENGTH(last_name)
HAVING COUNT(*)>5;
按多个字段分组
案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id;
添加排序
案例:查询每个部门每个工种的员工的平均工资,并按平均工资的高低显示
SELECT AVG(salary),department_id,job_id
FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id,job_id
HAVING AVG(salary)>10000
ORDER BY AVG(salary) DESC;
进阶6:连接查询
含义:又称多表查询 当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积:表1 有m行 表2 有n行 结果=m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类:
按年代分类:
sql92标准:仅仅支持内连接
sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接
按功能分类:
内连接:
等值连接
非等值连接
自连接
外连接:
左外连接
右外连接
交叉连接:
SELECT * FROM beauty;
SELECT * FROM boys;
SELECT NAME,boyName FROM boys,beauty
WHERE beauty.boyfriend_id=boys.id;
一、sql92标准
1.等值连接
多表等值连接的结果为多表的交集部分
n表连接,至少需要n-1个连接条件
多表的顺序没有要求
一般需要为表名取别名
可以搭配前面介绍的所有子句使用,比如排序、分组筛选
案例1:查询女神名和对应的男神名
SELECT NAME,boyName
FROM boys,beauty
WHERE beauty.boyfriend_id=boys.id;
案例2:查询员工名和对应的部门名
SELECT last_name,department_name
FROM employees,departments
WHERE employees.department_id=departments.department_id;
2.为表起别名
提高语言的简洁度
区分多个重名字段
注意:如果为表起了别名,则查询字段就不能使用原来的表名去限定了
查询员工名、工种号、工种名
SELECT e.last_name,e.job_id,j.job_title
FROM employees e,jobs j
WHERE e.job_id=j.job_id;
3.两个表的顺序是否可以调换
查询员工名、工种号、工种名
SELECT e.last_name,e.job_id,j.job_title
FROM employees e,jobs j
WHERE e.job_id=j.job_id;
4.可以加筛选
案例:查询有奖金的员工名、部门名
SELECT last_name,department_name,commission_pcT
FROM employees e,departments d
WHERE e.department_id=e.department_id
AND e.commission_pcT IS NOT NULL;
案例2:查询城市名中第二个字符为o的对应的部门名和城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.location_id =l.location_id;
AND city LIKE '_o%';
5.可以加分组
案例1:查询每个城市的部门个数
SELECT COUNT(*) 个数,city
FROM departments d,locations l
WHERE d.location_id=l.location_id
GROUP BY city;
案例2:查询有奖金的每个部门名和部门的领导编号和该部门的最低工资
SELECT department_name,d.manager_id,MIN(salary)
FROM departments d,employees e
WHERE d.department_id=e.department_id
AND commission_pcT IS NOT NULL
GROUP BY department_name,d.manager_id;
6.可以加排序
案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.job_id=j.job_id
GROUP BY job_title
ORDER BY COUNT(*) DESC;
7.可以实现三表连接
案例:查询员工名、部门名和所在城市
SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.department_id=d.department_id
AND d.location_id=l.location_id
AND city LIKE 's%';
ORDER BY department_name DESC;
2.非等值连接
案例1:查询员的工资和工资级别
SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.lowest_sal AND g.highest_sal;
SELECT salary employee_id FROM employees;
SELECT * FROM job_grades;
3.自连接
案例:查询 员工名 和上级名称
SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
FROM employees e,employees m
WHERE e.manager_id=m.manager_id