文章目录
- P33.数学函数
- P34.日期函数
- P37.加密函数
- P38.流程控制函数
- P39.查询增强
- P40.分页查询
- P41.分组查询
- P42.多子句查询
- P43.多表查询笛卡尔积(重难点)
- P44.多表查询
- P45.自连接
- P46.多行子查询
P33.数学函数
# 绝对值
SELECT ABS(-12) FROM DUAL;
# 十进制转为二进制
SELECT BIN(10) FROM DUAL;
# 向上取整
SELECT celling(-1.1) FROM DUAL;
# 向下取整
SELECT FLOOR(1.1) FROM DUAL;
# 保留n小数位数(四舍五入)
SELECT FORMAT(12.323412,3) FROM DUAL;
# 随机值
SELECT RAND() FROM DUAL;
# 伪随机值
SELECT RAND(1) FROM DUAL;
P34.日期函数
# 当前日期 2022-10-24
SELECT CURRENT_DATE() FROM DUAL;
# 当前时间
SELECT CURRENT_TIME() FROM DUAL;
# 当前时间戳
SELECT CURRENT_TIMESTAMP FROM DUAL;
# 创建一个测试表(测试current_timestamp的用法)
CREATE TABLE mes (
id INT,
content VARCHAR(30),
send_time DATETIME);
# 添加一条记录
INSERT INTO mes VALUES(1,'北京新闻',CURRENT_TIMESTAMP());
INSERT INTO mes VALUES(2,'上海新闻',NOW());
INSERT INTO mes VALUES(3,'广州新闻','2022-10-14 10:00:00');
SELECT * FROM mes;
# 显示所有的新闻信息,发布日期只显示日期,不显示时间
SELECT id,content,DATE(send_time) FROM mes;
# 请查询在十分钟内发布的帖子
SELECT *
FROM mes
WHERE DATE_ADD(send_time,INTERVAL 10 MINUTE)>NOW();
SELECT *
FROM mes
WHERE DATE_SUB(NOW(),INTERVAL 10 MINUTE)<send_time;
# 请用mysql的sql语句中求出2011-11-11和1990-1-1相差多少天
SELECT DATEDIFF('2011-11-11','1990-1-1') FROM DUAL;
-- 大的时间写在前面
# 请用sql语句求出你活了多少天
SELECT DATEDIFF(NOW(),'2002-9-11') FROM DUAL;
# 请用sql语句求出你大概活了多少年
SELECT DATEDIFF(NOW(),'2002-9-11')/365 FROM DUAL;
# 如果你能活到80岁,求出你还能活多少天
SELECT DATEDIFF(DATE_ADD('2002-9-11',INTERVAL 80 YEAR),NOW()) FROM DUAL;
ps:这里的datediff还可以把date换成time,datetime,timestamp等,比如:
# 我只希望看到当前日期和时间的时间部分
SELECT TIME(NOW()) FROM DUAL;
# 我只希望看到当前日期和时间的日期的月部分
SELECT MONTH(NOW()) FROM DUAL;
-- unix_timestamp: 返回的是从1970-1-1到现在的秒数
SELECT UNIX_TIMESTAMP(NOW()) FROM DUAL;
# from_unixtime可以把时间戳转换成想要的日期格式
# 意义,用一个整数记录时间,需要显示的时候转换
SELECT FROM_UNIXTIME(1666629079,'%Y-%m-%d %H:%i:%s') FROM DUAL;
ps:在开发中,一般都是用datetime直接记录时间,但是如果有人用int记录时间戳,你要知道后面他肯定要用from_unixtime转换函数来换成datetime的时间格式.
P37.加密函数
# 可以查询到登入mysql的有哪些用户,以及登录的ip
SELECT USER() FROM DUAL;
# 为字符串算出一个MD5 32的字符串,常用于加密
# root密码-->123456-->加密-->数据库存放的是加密后的
SELECT MD5('123456') FROM DUAL;
# 计算加密后密码的统一位数
SELECT LENGTH(MD5('123456')) FROM DUAL;
# 应用:加密后的密码的存入和查询
USE syh_db01;
CREATE TABLE login (
NAME VARCHAR(32),
PASSWORD CHAR(32) );
INSERT INTO login VALUES('song',MD5('syh'));
INSERT INTO login VALUES('li',MD5('123456'));
SELECT DISTINCT * FROM login;
SELECT DISTINCT NAME FROM login WHERE PASSWORD=MD5('123456');
- 这里求md5函数加密后的字符串的长度的时候,可以用到length(md5(string))
- 存到数据库的是加密后的密码,查询的时候也要用加密后的密码去查询
在一个数据库中想临时看一眼另一个数据库中的一个表的时候,为了不使用use databasename;反复切换数据库【要切换至少要两次】
我们可以使用select * from databasename.tablename
P38.流程控制函数
# if(expr1,expr2,expr3)如果expr1为true,则返回表达式expr2,否则返回expr3
SELECT IF(TRUE,'北京','上海') FROM DUAL;-- 返回的是北京
SELECT IF(FALSE,'北京','上海') FROM DUAL;-- 返回的是上海
#ifnull(expr1,expr2) 如果expr1不为空,则返回expr1,否则返回expr2
SELECT IFNULL(NULL,12) FROM DUAL;-- 返回12
SELECT IFNULL(13,'韩') FROM DUAL;-- 返回13
# 如果expr1为真,则返回epxr1,如果expr3为真,则返回expr4,否则返回expr5
# 多分支
SELECT CASE
WHEN TRUE THEN 'song'
WHEN TRUE THEN 'li'
ELSE 'chen' END;
-- 如果有两个都为真,则返回第一个为真的,if elseif
先来看看我们后面要用到的emp表:
INSERT INTO emp (sex_rename,birthday,entry_date,job,RESUME,image,NAME) VALUES('','2020-1-2','2022-1-3','打杂','简介','暂无','宋永红');
# 1. 查询emp表,如果id为空,则显示0.0
SELECT IFNULL(id,0.00) AS id是否为空 FROM emp;
SELECT IF(id IS NOT NULL,id,0.00) FROM emp;-- 判断的是等于用is,不是等于用is not
# 2.如果表的job是打杂,则显示小工,如果表是切菜,则显示长工
SELECT CASE
WHEN job='打杂' THEN '小工'
WHEN job='切菜' THEN '长工'
END FROM emp;
判断是否为空用is,判断其他是否是某一个值用=
job is not null
job='song'
P39.查询增强
看一下我们的笔记大纲:
我们之前讲的select查询都是基于一张表的单表查询.这里我们开始通过查询增强过渡到多表查询了
# 查询增强
SELECT * FROM emp;
# 使用where子句 查询2022-1-1后入职的员工
-- 老韩说明:在mysql中,日期类型可以直接比较
SELECT * FROM emp
WHERE entry_date>'2022-01-01';
# like模糊查询
-- %表示0-多个任意字符,_表示单个任意字符
# 如何查询首字母为s的员工姓名和工作
SELECT NAME,job FROM emp
WHERE NAME='s%';
# 如何查询第三个字符为大写o的所有员工的姓名和工作
SELECT NAME,job FROM emp
WHERE NAME='__O%';
# 如何查询没有id的雇员的姓名
SELECT NAME FROM emp
WHERE id IS NULL;
# 查询表结构
DESC emp;
# 使用order by子句
-- 升序排入职时间
SELECT * FROM emp
ORDER BY entry_date;
P40.分页查询
当数据的记录多的时候,比如有10w行,不可能通过一个页面来显示,所以我们就得知道如何分页查询
# 分页查询
# 1.按雇员的id好升序取出,每一页显示3条记录,请分别显示第1页,第2页...
-- 基本语法: select...limit start rows 表示从start+1行开始取,start从0开始计算
SELECT * FROM emp
ORDER BY id;-- 升序
SELECT * FROM emp
ORDER BY id
LIMIT 0,3;-- 第一页
SELECT * FROM emp
ORDER BY id,
LIMIT 6,9; -- 第二页
推导一个公式
SELECT * FROM emp
ORDER BY id
LIMIT 每一页显示的记录数*(第几页-1),每一页显示的纪律数;
P41.分组查询
-- 增强group by的使用
# 显示"各种岗位"的雇员总数,平均工资
SELECT COUNT(*),AVG(sal),job FROM emp
GROUP BY job;
# 显示雇员总数,以及获得补助的雇员数量
SELECT COUNT(*),COUNT(comm) FROM emp;
-- 老师的拓展要求
SELECT COUNT(*),COUNT(IF(comm IS NULL,1,NULL)) FROM emp;
-- 或者
SELECT COUNT(*)-COUNT(comm) FROM emp;
# 显示管理者的总人数(提示:一个管理者可能管理多个部门)
-- 先理解下面的去重的效果
SELECT DISTINCT mgr FROM emp;
SELECT COUNT(DISTINCT(mgr)) FROM emp; -- 先去重再计算个数
# 显示雇员工资的最大差额
SELECT MAX(sal)-MIN(sal) FROM emp;
P42.多子句查询
# 应用案例:请统计各个部门group by 的平均工资 avg
# 并且是大于1000的 having 并且按照平均工资从高到低排序 order by
# 取出前两行记录 limit
SELECT dep,AVG(sal) FROM emp
GROUP BY dep
HAVING avg_sal>1000
ORDER BY 0,2;
P43.多表查询笛卡尔积(重难点)
# 多表查询
-- 显示雇员名,雇员工资和所在部门的编号
# 老韩分析
-- 1.雇员名和雇员工资 来自emp表
-- 2.雇员所在编号 来自dep表
SELECT * FROM emp,login;
# 这样两个表的组合,是还没有写过滤条件的笛卡尔积
# 多表查询的目的就是找出正确的"笛卡尔积"
# 所以多表查询的重难点就是找出过滤条件
# +上过滤条件
SELECT NAME,salary,deptname FROM emp,login
WHERE emp.deptno=dep.deptno;
-- 注意:这里不能加上显示deptno,因为这合并的表中有两个deptno
-- 但是我们可以指定显示某一个表的列emp.deptno
ps:多表查询的条件不能少于表的个数-1
P44.多表查询
注意这里where子句使用and连接表示逻辑与
SELECT COUNT(*) FROM course,scores,student
WHERE scores.s_id=student.id AND scores.c_id=course.id;
# 如何显示每一个员工的姓名,工资来自emp13
-- 工资级别 salgrade 5
SELECT ename,sal,grade
FROM emp,salgrade
WHERE sal BETWEEN losal AND hisal;
写sql思路:
- 先写一个全笛卡尔积
- 然后写过滤条件
- 然后再选择表中显示哪些数据
P45.自连接
ps:自连接的特点:
- 一张表作为两张表使用
- 表必须起两个表别名
SELECT worker.ename AS '职员名',boss.ename AS '老板名' FROM emp worker,emp boss
WHERE worker.mar=boss.empno;
一张表通过起表别名来作为两张表使用,此时显示的前面必须加上是哪一个别名的ename
P46.多行子查询
-- 子查询的演示
-- 请思考:怎么查询到smith同一个部门的所有员工
/* 1.先查询到smith所在的部门号
2.然后把上面的select 语句当作一个子查询
*/
SELECT deptno FROM emp
WHERE ename='smith';
SELECT * FROM emp
WHERE deptno=(
);
# 合并后
SELECT * FROM emp
WHERE deptno=(
SELECT deptno FROM emp
WHERE ename='smith';
);
先拿到smith所在的编号,然后显示编号等于smith所在编号的所有信息.
# 课堂练习:如何查询和部门10的工作相同的雇员的
# 名字,岗位,工资,部门号,但是不含自己的
-- 查询部门10的工作
SELECT DISTINCT job FROM emp
WHERE deptno=10;
-- 将上面的查询结果当作子查询使用
SELECT ename,job,sal,deptno FROM emp
WHERE job IN(
SELECT DISTINCT job FROM emp
WHERE deptno=10;
) AND deptno!=10;
mysql中的等于=
不等于!=
不等于也可以用<>