一、DQL
DQL(Data Query Language) 数据查询语言,用来查询数据库中表的记录(数据)。
1.1、去除重复记录(DISTINCT)
SELECT DISTINCT 字段列表 FROM 表名;
查询xxl_job_group表中app_name和title字段的值并去重,
select distinct app_name,title
from xxl_job_group;
注意:这个查询出来的结果,只有当app_name、title完全一样才会去重。下面的结果就不会去重。
1.2 、起别名(AS)
AS 也可以省略
查询姓名、数学成绩、英语成绩。并通过as给math和english起别名(as关键字可以省略)
select name,math 数学成绩,english 英文成绩 from stu;
1.3、条件列表中的运算符
注意:null值的比较不能使用 = 或者 !=,需要使用 is 或者 is not
1.4、模糊查询(注意:%要在单引号里面)
(1)_ : 代表单个任意字符
(2)% : 代表任意个数字符
1.4.1、查询姓'马'的学员信息(名字由马开头的)
select * from stu where name like '马%';
1.4.2、查询姓名中包含'马',且不是第一个字开头的
select * from stu where name like '%马';
1.4.3、查询姓名中包含 '马' 的学员信息
select * from stu where name like '%马%';
1.4.4、查询第二个字是'花'的学员信息
select * from stu where name like '_花%';
1.5、排序查询
SELECT 字段列表 FROM 表名 ORDER BY 排序字段名1 [排序方式1],排序字段名2 [排序方式2] …;
ASC : 升序排列 (默认值)
DESC : 降序排列
查询学生信息,按照数学成绩降序排列,如果数学成绩一样,再按照英语成绩升序排列
select * from stu order by math desc , english asc ;
1.6、聚合函数
注意:null 值不参与所有聚合函数运算
统计班级一共有多少个学生
select count(id) from stu;
上面语句根据某个字段进行统计,如果该字段某一行的值为null的话,将不会被统计。所以可以在count(*) 来实现。* 表示所有字段数据,一行中也不可能所有的数据都为null,所以建议使用 count(*)
1.7、分组查询
SELECT 字段列表 FROM 表名 [WHERE 分组前条件限定] GROUP BY 分组字段名 [HAVING 分组后条件过滤];
注意:分组之后,查询的字段为聚合函数和分组字段,查询其他字段无任何意义
表中的数据为
下面的sql语句中查询name就毫无意义:
select name, sex, avg(math) from stu group by sex;
得到查询出结果:
我们发现查询出来的name为好伟大和卢本伟,这个对应的是sex为女和男时的第一个数据。
也就是说查询的字段不是聚合函数也不是分组字段,那么查询出来的结果就是这个字段对应的第一笔数据,没有任何意义。
查询男同学和女同学各自的数学平均分,以及各自人数,要求:分数低于70分的不参与分组,分组之后人数大于2个的
select sex, avg(math),count(*) from stu where math > 70 group by sex having count(*) > 2;
也就是说使用了group分组之后,查询条件中没有分组的列,例如math等字段,必须使用聚合函数查询出来,例如上面的avg(math)、,count(*),没有使用聚合函数查询出来的字段,会是一个任意值,通常是表中的第一个值,所以查询出来的结果并不准确。
where 和 having 区别:
执行时机不一样:where 是分组之前进行限定,不满足where条件,则不参与分组,而having是分组之后对结果进行过滤。
可判断的条件不一样:where 不能对聚合函数进行判断,having 可以。
1.7.1、隐式分组
查询申请表中:每一个用户最新的申请id
select la1.BUSI_ID
from t_application la1
where la1.CREATE_TIME=(
select MAX(la2.CREATE_TIME)
from t_application la2
where la1.USER_NO=la2.USER_NO
)
这里的子查询会将用户先进行分组,然后查询出每个用户最新的创建时间(CREATE_TIME),
再把最新的创建时间和la1中的CREATE_TIME进行关联,这样就能得到每个用户最新的创建时间对应的申请id
select la1.BUSI_ID,USER_NO
from t_application la1
where la1.CREATE_TIME=(
select MAX(la2.CREATE_TIME)
from t_application la2
where la1.USER_NO=la2.USER_NO
group by la2.USER_NO
)
这两个sql的结果是一样的,所以在子查询中可以省略分组grop by的操作,子查询中会对拼接条件进行分组,例如上面的连接条件是USER_NO,所以在子查询中会对USER_NO进行隐式的分组。
1.8、创建临时表进行多表查询
上面通过子查询得到的结果也能通过创建临时表完成。
select la.USER_NO,la.BUSI_ID
from t_application la
inner join
(select USER_NO,MAX(t.CREATE_TIME) as CREATE_TIME
from t_application t
group by t.USER_NO)ta
on la.USER_NO=ta.USER_NO
and la.CREATE_TIME=ta.CREATE_TIME
首先在申请表中对用户进行分组,查询出每个用户的客户id以及最大申请时间,再把这个查询结果当做一张临时表ta
然后在主查询中使用inner join 关联这张临时表ta,就能控制查询结果是用户最新的一笔申请订单。再通过这个条件查询出用户的客户id
1.9、limit的用法
select * from t_user limit 5;
从第一条开始取5条数据
Limit还有分页查询等用法,这里不做详细介绍。
分页查询 limit 是MySQL数据库的方言
Oracle 分页查询使用 rownum
SQL Server分页查询使用 top
总结:
查询SQL的书写顺序:
select-> from->where->group by->having->order by->limit