数据库类型分为关系型数据库(比如MySQL)和非关系型数据库(NoSQL)。
数据库管理系统(DBMS):国内常见的有MySQL,Oracle等。
结构化查询语言(SQL,Structured Quary Language):
1.DQL,数据查询语言,select
2.DDL,数据定义语言,修改的是表结构,create,alter,drop
3.DML,数据操纵语言,对表数据进行操作,insert,update,delete
4.DCL,数据控制语言,权限问题,grant,revoke
5.TPL,数据事务管理语言,commit,rollback
6.CCL,指针控制语言
DQL语言简介
DQL(Data Query Language)是SQL的子集,专门用于数据查询操作,核心命令为SELECT。它不修改数据,仅从数据库中检索信息,是数据分析、报表生成的基础工具。
基本语法结构
SELECT column1, column2
FROM table_name
WHERE condition
GROUP BY column
HAVING group_condition
ORDER BY column
LIMIT offset, count;
-
SELECT:指定查询的列(可使用*表示所有列)。select后面既可以跟变量也可以跟常量。
-
FROM:指定数据来源的表。
-
WHERE:过滤行级数据(不可与聚合函数共用)。
-
GROUP BY:按列分组,常与聚合函数(如SUM、COUNT)配合使用。
-
HAVING:过滤分组后的数据(类似WHERE,但用于聚合结果)。
-
ORDER BY:排序(ASC升序,DESC降序)。
-
LIMIT:限制返回行数。
-
DISTINCT:去重。(只能出现在所有字段之前)
数据处理函数
字符串相关
转大写upper和ucase。例如
select upper(ename) as ename from emp;
转小写lower和lcase。同上。
截取字符串substr。语法:substr('被截取的字符串',起始下标,截取长度)。
有两种写法:
第一种:substr(''被截取的字符串',起始下标,截取长度)
第二种:substr('被截取的字符串',起始下标)
select substr('abcdef',2,3);
注意:起始下标从1开始,不是从0开始。(1表示从左侧开始的第一个位置,-1表示从右侧开始的第一个位置。)不管是1还是-1都是从左往右截取。
练习:找出员工名字中第二个字母是A的
select ename from emp where substr(ename,2,1)='A';
获取字符串长度length
select length('你好123');
length统计字节长度,输出结果为7(一个汉字两个字节)。
select char_length('你好123');
char_length统计字符个数,输出结果为5。
字符串拼接
语法:concat('字符串1','字符串2')
拼接的字符串数没有限制。
去除字符串前后空白trim
默认是去除前后空白,也可以进行去除指定的前缀后缀。
去除前置0,例如:
select trim(leading '0' from '000111000');
去除后置0,例如:
select trim(trailing '0' from '000111000');
前置0和后置0都去除:
select trim(both '0' from '000111000');
rand()生成0到1的随机浮点数。
rand(x)生成0到1的随机浮点数,通过指定整数x来确定每次获取到相同的浮点值。
round(x)四舍五入,保留整数位,舍去所有小数。
round(x,y)四舍五入,保留y位小数。
truncate(x,y)舍去,例如
select truncate(9.999,2);
输出结果为9.99。以上SQL表示保留两位小数,剩下的全部舍去。
ceil函数:返回大于或等于数值x的最小整数。
floor函数:返回小于或等于数值x的最大整数。
空处理
ifnull(x,y),空处理函数,当x为NULL时,将x当作y处理。
infnull(comm,0),表示如果comm是null时当做0处理。
在SQL语句中,凡是有NULL参与的数学运算,最终的结算结果都是NULL。
now():获取的是执行select语句的时刻。
sysdate():获取的是执行sysdate()函数的时刻。
curdate():获取当前日期。
date_add函数的作用:给指定的日期添加间隔的时间,从而得到一个新的日期。
date_add函数的语法格式:date_add(日期,inter expr单位),例如
select date_add('2023-01-09',interval 3 day);
#输出为2023-01-06
注:日期:一个日期类型的数据
interval:关键字,翻译为‘间隔’,固定写法。
expr:指定具体的间隔量,一般为数字。也可以为数字,若为负数,效果和date_sub函数相同。
单位:year,month,day,hour,minute,second,microsecond,week,quarter
复合型单位:a_b,写法如
select date_add('2022-10-01 10:10:10',interval '3,2' day_hour);
#输出为2022-10-04 12:10:10
date_format日期格式化函数
将日期转换为具有某种格式的日期字符串,通常用在查询操作中。(date类型转换为char类型)
语法格式:date_format(日期,'日期格式')
该函数有两个参数:
·第一个参数:日期。这个参数就是即将要被格式化的日期。类型是date类型。
·第二个参数:指定要格式化的格式子字符串。
○%Y:四位年份
○%y:两位年份
○%m:月份(1…12)
○%d:日(1….30)
○%H:小时(0…23)
○i:分(0…59)
○s:秒(0…59)
注意:在mysql中,默认的日期格式就是:%Y-%m-%d %H:%i:%s,所以直接输出日期数据时,会自动转化成该格式的字符串。
str_to_date函数
作用是将char类型的日期字符串转换成日期类型date,通常使用在插入和修改操作当中。(char类型转换成date类型)
dayofweek,dayofmonth,dayofyear函数
示例:
select dayofweek(now());
#一周中的第几天
last_day函数:获取给定日期所在月的最后一天的日期
select last_day(now());
datediff函数:计算两个日期之间所差天数。(时分秒不算,只算天数)
select datediff('1970-02-01 20:10:30','1970-01-01');
timediff函数:计算两个日期所差时间。
select timediff('1970-01-02 20:10:30','1970-01-01 20:09:30');
#输出为24:01:00
if函数
如果条件为TRUE则返回“YES”,如果条件为“FALSE”则返回“NO”:
select if(500<1000,"YES","NO");
再例如:工作岗位是M的工资上调10%,是S的工资上调20%,其他岗位工资照常。(嵌套)
select ename,sall,job,if(job='M',sal*1.1,if(job='S',sal*1.2,sal)) as newsal from emp;
这个需求也可以用case…when…then…when…then…else…end来完成。
select ename,job,
case job
when 'M' then sal*1.1
when 'S' them sal*1.2
else sal
end
as sal
from emp;
cast函数:用于将值从一种数据类型转换为表达式中指定的另一种数据类型
语法:cast(值 as 数据类型)
可用的数据类型有date(日期类型),time(时间类型),datetime(日期时间类型),signed(有符号的int类型,有符号指的是正负数),char(定长字符串类型),decimal(浮点型)。
select cast(123.456 as char(4));#输出为123.
select cast(123.456 as char(3));#输出为123
select cast('1234.456' as decimal(5,1));#输出结果为1234.5.decimal(5,1)指的是保留五位有效数字,保留一位小数。
加密函数md5:可以将给定的字符串经过md5算法进行加密处理,字符串经过加密后会生成一个固定长度32位的字符串,md5加密之后的密文通常是不能解密的。
分组函数
执行原则:先分组,然后对每一组数据执行分组函数,如果没有分组语句group by的话,整张表的数据自成一组。分组函数包括:max最大值,min最小值,avg平均值,sum求和,count计数。
select max(sal) from emp;#max可替换为min,avg等分组函数
分组查询
group by
按照某个字段分组,或者按照某些字段联合分组。注意:group by的执行是在where之后执行的。
语法:
group by字段
group by字段1,字段2….
当select语句中有group by的话,select后面只能跟分组函数或参加分组的字段。例如:
select ename,deptno,avg(sal) from emp group by ename,deptno;
#正常运行,找出每个部门不同人的薪资
select ename,deptno,avg(sal) from emp group by deptno;
#报错
having
having写在group by 后面,当你对分组之后的数据不满意,可以继续通过having对分组之后的数据进行过滤。
where的过滤是在分组前进行过滤。
使用原则:尽量在where中过滤,实在不行再使用having,越早过滤效率越高。
找出除20部分之外,其他部门的平均薪资
select deptno,avg(sal) from emp where deptno<>20 group by deptno; //建议
select deptno,avg(sal) from emp group by deptno having deptno<>20; //不建议
查询每个部门平均薪资,找出平均薪资高于2k的
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
组内排序
substring_index函数
select substring_index('http://www.baidu.com', ',' ,1);
#输出为http://www
select substring_index('http://www.baidu.com', ',' ,2);
#输出为http://www.baidu
group_concat函数
#将分组(Group By)后的多行数据合并成一个字符串。常用于将一对多关系中的“多”方数据展示在一行中。
select group_concat(empno order by sal desc) from emp group by job;
总结单表的DQL语句
select …5
from …1
where …2
group by …3
having …4
order by …6
连接查询
从一张表中查询数据称为单表查询;从两张或更多张表中联合查询数据成为多表查询,又叫做连接查询。
(主要学SQL99)
根据连接方式的不同进行分类:
1.内连接
1.等值连接
2.非等值连接
3.自连接
2.外连接
1.左连接
2.右连接
3.全连接(MySQL不学)
笛卡尔积现象
1.当两张表进行连接查询时,如果没有任何条件进行过滤,最终的查询结果条数是两张表条数的乘积。为了避免笛卡尔积现象的发生,需要添加条件进行筛选过滤。
2.需要注意:添加条件后,虽然避免了笛卡尔积现象,但是匹配的次数没有减少。
3.为了SQL语句的可读性,为了执行效率,建议给表起别名。
select e.ename,d.dname from emp e,dept d;#起别名,as省略
内连接
满足条件记录的才会出现在结果集中。
内连接之等值连接
连接时,条件为等量关系。


内连接之非等值连接

内连接之自连接
select
e.ename员工名,l.ename领导名
from
emp e
join
emp l
on
e.mgr = l.empno;

外连接

区别
找出每个员工的上级领导,要求展示所有的员工
#内连接
select e.ename 员工 l.ename 领导 from emp e join emp l on e.mgr=l.empno;
#左外连接
select e.ename 员工 l.ename 领导 from emp e left join emp l on e.mgr=l.empno;
#右外连接
select e.ename 员工 l.ename 领导 from emp l right join emp e on e.mgr=l.empno;
多张表连接
select e.ename,d.name,s.grade
from emp e
join dept d
on e.deptno=d.deptno
join salgrade s
on e.sal between s.losal and s.hisal;
#结合之前所有学的可以发现select后面是筛选目标,from后是第一张表,join第二张表on条件,然后筛选
子查询
select语句中嵌套select语句就叫子查询。
select语句可以嵌套在哪里?
1.where后面,from后面,select后面都是可以的。
2.exists
where后面使用子查询
找出高于平均薪资的员工姓名和薪资。
#错误示范
select ename,sal from emp where sal>avg(sal);
错误原因:where后面不能直接使用分组函数
但是可以使用子查询:
select ename,sal from rmp where sal>(select av(sal) from emp);
from后面使用子查询
#案例:找出每个部门平均工资等级。
#第一步:先找出每个部门平均工资。
select deptno ,avg(sal) avgsal from emp group by deptno;
#第二步:将以上查询结果当作临时表t,t表和salgrade表进行连接查询。
#条件:t.avgsal between s.losal and s. hisal
select t.*,s.gradenfrom(select deptno,avg(sal) avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and s.hisal;
select后面使用子查询
select e.ename,(select d.dname from dept d where e.deptno = d.deptno)as dname from emp e;
exists,not exists
在数据库中,EXISTS(存在)用于检查子查询的查询结果行数是否大于0.如果子查询的查询结果行数大于0,则EXISTS条件为真。(即存在查询结果限制则是TRUE)。
主要应用场景:
·EXISTS可以与SELECT,UPDATE,DELETE一起使用,用于检查另一个查询是否返回任何行;
·EXISTS可以用于验证条件子句中的表达式是否存在;
·EXISIS常用于子查询条件过滤。

in和exists区别
in和exists都是用于关系型数据库查询的操作符,不同之处在于:
1.in操作符是根据指定列表中的值来判断是否满足条件,而exists操作符则是根据子查询的结果是否有返回记录集来判断。
2.exists操作符通常比in操作符更快,尤其是在子查询返回记录数很大的情况下。因为exists只需要判断是否存在符合条件的记录,而in操作符需要比对整个列表,因此执行效率更低。
3.in操作符可同时匹配多个值,exists只能匹配一组条件。

union,union all
不管是union还是union all都可以将两个查询结果集进行合并。
union会对合并之后的查询结果集进行去重操作。
union all是直接将查询结果集合并,不进行去重操作,效率更高。
limit
作用:查询第几条到第几条的记录。通常是因为表中数据量太大,需要分页显示。
语法格式:limit 开始下标,长度






