数据库--使用DQL命令查询数据(二)
数据库–使用DQL命令查询数据(二)
文章目录
- 1.连接查询(多表查询)
- 1.1内连接查询
- 1.2外连接查询
- 2.不同的SQL 的JOIN对比
- 3.自连接查询
- 4.ORDER BY排序
- 5.LIMIT
- 6.子查询
- 7.GROUP BY分组
- 8.MYSQL函数
- 8.1窗口函数
- 8.2字符串函数
- 8.3日期函数
- 8.4聚合函数
- 9.表合并(UNION与UNION ALL)
1.连接查询(多表查询)
- 连接查询
- 如需要多张数据表的数据进行查询,则可通过连接运算符实现多个查询
- 分类包括
- 内连接 ( inner join)
- 等值和非等值的连接查询
- 自身连接查询
- 外连接 ( out join )
- 左外连接(LEFT JOIN)
- 右外连接 ( RIGHT JOIN)
- 内连接 ( inner join)
1.1内连接查询
- 在表中至少一个匹配时,则返回记录
SELECT 字段1,字段2,...FROM table_1
INNER JOIN table_2 ON table_1.字段x=table_2.字段y;
# INNER JOIN 与 JOIN 是相同的;
# 若table_1中的行在table_2中没有匹配,则不返回;
#要求:从subject和grade数据表查询课程名称和所属年级名称
SELECT SubjectName '课程名称',GradeName '所属年级名称'
FROM `subject`,grade
WHERE `subject`.GradeID=grade.GradeID;SELECT SubjectName '课程名称',GradeName '所属年级名称'
FROM `subject`INNER JOIN grade
WHERE `subject`.GradeID=grade.GradeID;
- 等值和非等值的连接查询
- 与单表查询类似,都是SELECT语句
- 把多个表放到FROM后,并用逗号隔开
- 可使用AS关键字取别名,便于引用
- 如无重名查询字段则可省略数据表的指定
#要求:从subject和grade数据表查询课程名称和所属年级名称
SELECT SubjectName '课程名称',GradeName '所属年级名称'
FROM `subject`,grade #返回记录数为两表记录数的乘积SELECT SubjectName '课程名称',GradeName '所属年级名称'
FROM `subject`,grade
WHERE `subject`.GradeID=grade.GradeID; #等效于内连接
1.2外连接查询
-
左外连接(LEFT JOIN)
-
从左表(table_1)中返回所有的记录,即便在右(table_2)中没有匹配的行
SELECT 字段1,字段2,...FROM table_1 LEFT JOIN table_2 ON table_1.字段x = table_2.字段y;SELECT SubjectName '课程名称',GradeName '所属年级名称' FROM subject LEFT JOIN grade ON `subject`.GradeID=grade.GradeID;
-
-
右外连接(RIGHT JOIN)
-
从右表(table_2)中返回所有的记录,即便在左(table_1)中没有匹配的行
SELECT 字段1,字段2,...FROM table_1 RIGHT JOIN table_2 ON table_1.字段x = table_2.字段y;
-
-
练习:查询学生表(student)的学号(studentNo),姓名(StudentName)和所在年级(GradeName)
#左连接查询方式 SELECT StudentNO '学号',StudentName '姓名',GradeName '所在年级' FROM student LEFT JOIN grade ON student.GradeID=grade.GradeID;#右连接查询方式 SELECT StudentNO '学号',StudentName '姓名',GradeName '所在年级' FROM student RIGHT JOIN grade ON grade.GradeID=student.GradeID;#内连接查询方式 SELECT StudentNO '学号',StudentName '姓名',GradeName '所在年级' FROM student INNER JOIN grade ON student.GradeID=grade.GradeID;
左连接查询结果
右连接查询结果
内连接查询结果
2.不同的SQL 的JOIN对比
操作符名称 | 描述 |
---|---|
INNER JOIN ( JOIN ) | 两张表连接,两张表字段完全匹配才返回数据 |
LEFT JOIN | 以左表为主表进行连接,返回左表中所有数据 |
RIGHT JOIN | 以右表为主表进行连接,返回右表中所有数据 |
3.自连接查询
-
数据表与自身进行连接
-
从一个包含栏目ID,栏目名称和父栏目ID的表中,查询父栏目名称和其子栏目名称,表结构如下:
#表结构语句 CREATE TABLE IF NOT EXISTS category(categoryId int(10) auto_increment primary key,categoryName varchar(32) not null ,pid int(10) );
-
4.ORDER BY排序
- ORDER BY排序查询
- 对SELECT语句查询得到的结果,按某些字段进行排序
- 与DESC(降序排列)或ASC(升序排列)搭配使用,默认为ASC
#查询《高等数学-1》的所有考试结果,并按成绩由高到低排列
SELECT StudentResult,SubjectName
FROM result
LEFT JOIN `subject` ON result.SubjectNo=`subject`.SubjectNO
WHERE SubjectName='高等数学-1'
ORDER BY StudentResult DESC;
5.LIMIT
-
LIMIT [m,]n 或 LIMIT n OFFSET m
-
限制SELECT返回结果的行数
-
m 制定第一个返回记录行的偏移量
-
n 制定返回记录行的最大数目
#返回前5条记录 SELECT StudentNo,SubjectNo,ExamDate,StudentResult FROM result LIMIT 5;#返回6-15条记录 SELECT StudentNo,SubjectNo,ExamDate,StudentResult FROM result LIMIT 5,10;#查询所有《数据库结构-2》的考试成绩,并按照由高到低显示,同时把该成绩对应的学生的学号、姓名打印出来 SELECT s.StudentNo '学号',StudentName '姓名',r.StudentResult '成绩',a.SubjectName FROM result r LEFT JOIN student s ON r.StudentNo=s.StudentNo LEFT JOIN `subject` a ON r.SubjectNo=a.SubjectNO WHERE a.SubjectName='数据库结构-2' ORDER BY StudentResult DESC #第一次查询前5条记录 LIMIT 5;#练习:查询《JAVA第一学年》课程成绩前10名且分数大于80的学生信息 (学号,姓名,课程名,分数) SELECT student.StudentNo '学号',StudentName '姓名',SubjectName'课程名',StudentResult '分数' FROM result LEFT JOIN student ON student.StudentNo=result.StudentNo LEFT JOIN `subject`ON result.SubjectNo=`subject`.SubjectNO WHERE StudentResult>80 AND SubjectName='JAVA第一学年' ORDER BY StudentResult DESC LIMIT 10;
-
注:
- m不指定则偏移量为0,从第一条开始返回前n条记录
- LIMIT 常用于分页显示
6.子查询
-
在查询语句中的WHERE条件子句中,又嵌套了另外一个查询语句
-
列子查询 单行单列
#获得所有学生信息,并获得年级名称 SELECT a.StudentNo,a.StudentName,a.GradeId, (SELECT b.GradeName FROM grade b WHERE a.GradeID=b.GradeID ) gname FROM student a;
-
表子查询 必须起别名
-
条件子查询 单行单列 多行单列
#获得高等数学-1的考试成绩信息 SELECT a.StudentNo,a.SubjectNo,a.StudentResult FROM result a WHERE a.SubjectNo=(SELECT b.SubjectNo FROM `subject` b WHERE b.SubjectName='高等数学-1');#获得大一,大二,大三的学生信息 SELECT a.StudentNo,a.StudentName,a.GradeId FROM student a WHERE a.GradeId IN(SELECT b.GradeID FROM grade b WHERE b.GradeName IN('大一','大二','大三'));
注:嵌套查询可由多个子查询组成,求解的方式是由里及外,子查询返回的结果一般都是集合,故而建议使用 IN 关键字
7.GROUP BY分组
- 使用GROUP BY关键字对查询结果分组
- 对所有的数据进行分组统计
- 分组的依据字段可以有多个,并依次分组
- 与HAVING结合使用,进行分组后的数据筛选
#按照不同的课程分组,分别算出其平均分、最高分和最低分,对于低于60分平均分的不予显示
SELECT SubjectName '课程名',AVG(StudentResult) '平均数',MAX(StudentResult) '最高分',MIN(StudentResult) '最低分'
FROM result
LEFT JOIN `subject` ON result.SubjectNo=`subject`.SubjectNO
GROUP BY SubjectName
HAVING AVG(StudentResult)>60;
8.MYSQL函数
8.1窗口函数
-
row_number()
- row_number()over(partition by字段1 order by 字段2) 的结果是每一行记录生成一个序号,依次排序且排序的序号不会重复,例如1 2 3 4 5…
-
rank()
- rank()over(partition by字段1 order by 字段2) 的结果,若排序字段的值相同则其序号是一样的,后续不同字段值的序号为(前一行序号+N,其中N为前一个字段值重复的行数),例如1 1 3 4 4 4 7…
-
dense_rank()
- dense_rank()over(partition by字段1 order by 字段2) 的结果也会考虑排序字段值相同的情况,即排序字段的值相同那么他们的序号是一样的,但是与rank()的区别是后续不同字段值的序号为(前一行序号+1),例如1 1 2 2 3 4 5…
8.2字符串函数
-
LOWER 转换小写
-
UPPER 转换大写
-
concat 合并列
-
substr 截取字符串 从1开始
SELECT SUBSTR('MySQL Database',1,7);
-
CHAR_LENGTH 获取字符串长度
-
instr 查询某个字符串第一次出现的位置
SELECT INSTR('Hello World', 'World');//7
-
REVERSE 字符串反转
-
FORMAT 格式化
8.3日期函数
-
now(),sysdate(),current_timestamp,current_timestamp() 获得当前系统时间
SELECT NOW();
-
date_format(“日期”,‘%Y%m%d%H%i%s’) 格式化日期+时间
SELECT DATE_FORMAT(NOW(),'%Y%m%d%H%i%s');
-
to_days(日期) 获得从0000-00-00到现在的天数
select TO_DAYS(NOW());
-
date_add(日期,interval 1 day ) 为日期增加一个时间间隔 -1减
#加一天 select date_add(NOW(), interval 1 day); #加一年 select date_add(NOW(), interval 1 YEAR); #加一月 select date_add(NOW(), interval 1 MONTH); #减一天 select date_add(NOW(), interval -1 day);
-
datediff(date1,date2) 日期间隔天数
select datediff('2025-08-08', '2024-09-09');
8.4聚合函数
函数名称 | 描述 |
---|---|
COUNT( ) | 返回满足SELECT条件的记录总和数,如 SELECT COUNT(*)… |
SUM( ) | 返回数字字段或表达式列作统计,返回一列的总和 |
AVG( ) | 通常为数值字段或表达列作统计,返回一列的平均值 |
MAX( ) | 可以为数值字段、字符字段或表达式列作统计,返回最大的值 |
MIN( ) | 可以为数值字段、字符字段或表达式列作统计,返回最小的值 |
9.表合并(UNION与UNION ALL)
#查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
(SELECT a.s_id,a.c_id,a.s_score FROM score a
WHERE a.c_id='01' ORDER BY a.s_score DESC LIMIT 1,2)
UNION ALL
(SELECT a.s_id,a.c_id,a.s_score FROM score a
WHERE a.c_id='02' ORDER BY a.s_score DESC LIMIT 1,2)
UNION ALL
(SELECT a.s_id,a.c_id,a.s_score FROM score a
WHERE a.c_id='03' ORDER BY a.s_score DESC LIMIT 1,2);
-
UNION与UNION ALL的区别:
1、对重复结果的处理:UNION在进行表链接后会去重,UNION All不会。
2、对排序的处理:Union将会按照字段的顺序进行排序;UNION ALL只是简单的将两个结果合并后就返回。
-
UNION ALL 要比UNION效率高,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序时的话,那么就使用UNION ALL。