DQL查询数据
DQL(Data Query Language,数据查询语言)
-
查询数据库数据,如SELECT语句
-
简单的单表查询或多表的复杂查询和嵌套查询
-
数据库语言中最核心、最重要的语句
-
使用频率最高的语句
这些子句的使用顺序通常是:
-
SELECT
子句 -
FROM
子句 -
WHERE
子句 -
GROUP BY
子句 -
HAVING
子句 -
ORDER BY
子句 -
LIMIT
子句
SELECT 字段名 | * FROM 表名 [WHERE condition];
查询student表中所有的数据列
select * from student;
只查询student表中的学号、姓名、电话
SELECT StudentNo, StudentName, Phone FROM student;
AS子句
作用:
-
给数据列取一个新别名
-
给表取一个新别名
-
把经计算或总结的结果用另外一个新名称来代替
SELECT StudentNo AS '学号' FROM student;
SELECT a.StudentNo FROM student AS a;
SELECT Phone+1 AS Tel FROM student;
注意:AS可以省略不写
表也可以起别名,使用更加方便:select * from student a where a.GradeID in(1,2);
DISTINCT去重
去掉SELECT查询返回的记录结果中重复的记录(所有返回列的值都相同),只返回一条:
SELECT DISTINCT 字段名1, 字段名2... FROM 表名
#查询成绩表中的所包含的课程ID
SELECT DISTINCT SubjectNo FROM result;
#DISTINCT 结果去重
select DISTINCT a.studentName,a.LoginPwd from student a;
返回过程中可以使用表达式:
SELECT version() , 100*3 #返回MySQL版本和计算结果
SELECT SubjectName '课程名称', ClassHour+10 '新学时' FROM subject;
#给返回结果中的课时都加10个课时
where条件语句
-
逻辑操作符
操作符名称 | 语法 | 描述 |
---|---|---|
AND或&& | a AND b 或 a && b | 逻辑与,同时为真,结果才为真 |
OR或|| | a OR b 或 a||b | 逻辑或,只要一个为真,则结果为真 |
NOT或! | NOT a 或 !a | 逻辑非,若操作数为假,结果则为真 |
-
比较操作符
操作符名称 | 语法 | 描述 |
---|---|---|
IS NULL | a IS NULL | 若操作符为NULL,则结果为真 |
IS NOT NULL | a IS NOT NULL | 若操作符不为NULL,则结果为真 |
BETWEEN | a BETWEEN b AND c | 若a范围在b与c之间则结果为真 |
LIKE | a LIKE b | SQL模式匹配,若a匹配b,则结果为真 |
IN | a IN (a1,a2,a3,….) | 若a等于a1,a2…中的某一个,则结果为真 |
注意:
1、数值数据类型的记录之间才能进行算术运算
2、相同数据类型的数据之间才能进行比较
BETWEEN AND范围查询
根据一个范围值来检索,等同于 >= 和 <= 联合使用
SELECT 字段列1,字段2,… FROM 表名 WHERE 字段x BETWEEN 值1 AND 值2
#查询课程表中课时在110和120之间的所有记录
SELECT * FROM subject WHERE ClassHour BETWEEN 110 AND 120;
等同于:
SELECT * FROM subject WHERE ClassHour >= 110 AND ClassHour <= 120;
LIKE模糊查询
-
% --> 匹配0或任意多个字符
-
_ --> 匹配单个字符
#查询包含“数学”的所有课程
SELECT * FROM subject WHERE SubjectName LIKE "%数学%";
#查询所有姓名为“李**”三个字的学生信息
SELECT StudentNo,StudentName FROM student
WHERE StudentName LIKE "李__";
IN范围查询
SELECT 字段列1,字段2 ,…FROM 表名 WHERE 字段x IN ( 值1,值2,值3…)
in是等值查询,多个值之间用英文逗号隔开
SELECT * FROM subject where ClassHour = 100 OR ClassHour =110 OR ClassHour = 120; #普通处理方式
SELECT * FROM subject where ClassHour IN ( 100, 110,120 );
空值条件查询
NULL --> 无值
空符串 --> " "
使用 IS NULL 或 IS NOT NULL 比较操作符去比较,空字符串等于号比较 =" "
#获得姓名为空的学生信息
select *from student a where a.studentName='':
#获得姓名不为空的学生信息
select * from student a where a.studentName is not null:
连接查询
多张数据表的数据进行查询,则可通过连接运算符实现多个查询
-
内连接 ( inner join)
-
等值和非等值的连接查询
-
自身连接查询
-
-
外连接 ( out join )
-
左连接(LEFT JOIN)
-
右连接 ( RIGHT JOIN)
-
INNER JOIN内连接
在表中至少一个匹配时,则返回记录
SELECT 字段1,字段2,… FROM table1
INNER JOIN table2 ON table1.某字段 = table2.某字段;
# INNER JOIN 与 JOIN 是相同的;
# 如table1中的行在table2中没有匹配,则不返回;
从subject和grade数据表查询课程名称和所属年级名称:
SELECT SubjectName,GradeName FROM subject INNER JOIN grade ON 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;
外连接
左外连接(LEFT JOIN)
从左表(table1)中返回所有的记录,即便在右(table2)中没有匹配的行
SELECT 字段1,字段2,… FROM table1
LEFT [ OUTER ] JOIN table2 ON table1.字段x = table2.字段y;
右外连接(RIGHT JOIN)
从右表(table2)中返回所有的记录,即便在左(table1)中没有匹配的行
SELECT 字段1,字段2,… FROM table1
RIGHT [ OUTER ] JOIN table2 ON table1.字段x = table2.字段y;
JOIN对比
操作符名称 | 描述 |
---|---|
INNER JOIN ( JOIN ) | 如果表中有至少一个匹配,则返回行 |
LEFT JOIN | 不论右表是否有匹配,都会返回左表的所有行 |
RIGHT JOIN | 不论左表是否有匹配,都会返回右表的所有行 |
自连接查询
数据表与自身进行连接,从一个包含栏目ID,栏目名称和父栏目ID的表中,查询父栏目名称和其子栏目名称,表结构如下:
#表结构语句
CREATE TABLE IF NOT EXISTS category(
categoryId int(10) auto_increment primary key,
categoryName varchar(32) not null ,
pid int(10)
);
GROUP BY分组
使用GROUP BY关键字对查询结果分组
-
对所有的数据进行分组统计
-
分组的依据字段可以有多个,并依次分组
-
与HAVING结合使用,进行分组后的数据筛选
计数、求和:
SELECT sid, COUNT(DISTINCT cid) AS courses_count, SUM(score) AS total_score
FROM table_name
GROUP BY sid;
按学号进行分组,计算每个学生选课的总数以及所有课程的总成绩。
在 SQL 中,COUNT(*)
和 COUNT(column_name)
是两种不同的方式来计算行数的方法。
COUNT(*):
-
COUNT(*)
是一种特殊的计数方式,它会统计符合条件的所有行的数量,不考虑任何列是否为 NULL。具体来说:-
如果没有指定 WHERE 子句,它将返回表中的所有行数。
-
如果有 WHERE 子句,它将返回符合 WHERE 子句条件的行数。
-
-
COUNT(*)
不关心是否具体列的值是否为 NULL,因为它只是计算行数。
COUNT(column_name):
-
COUNT(column_name)
是另一种计数方式,它会统计指定列column_name
非 NULL 值的行数。 -
如果
column_name
的值为 NULL,那么COUNT(column_name)
不会将其计入统计。
为什么要使用 COUNT(*)而不是 COUNT(t_name)呢?
-
准确性和性能:通常情况下,使用
COUNT(*)
更为简单和高效。它不需要关心具体的列名或者列中的值,只需计算行的数量。这在性能上可能更优,尤其是在大型表中或者在不需要考虑特定列值的情况下。 -
避免误用:如果使用
COUNT(t_name)
,假设t_name
是某一列名,那么它将只计算该列中非 NULL 值的行数。如果你的目标是计算整个表的行数,这种方式可能会导致误解和错误的统计结果,因为它不会考虑所有行,只会考虑指定列中非 NULL 值的行。
HAVING过滤
使用having对聚合结果进行过滤。
使用 HAVING 子句来过滤出平均成绩小于60分的同学。
SELECT s.s_id '学号', s.s_name '姓名', AVG(o.score) AS '平均分'
FROM student s
JOIN score o ON s.s_id = o.s_id
GROUP BY s.s_id, s.s_name
HAVING AVG(o.score) < 60;
注意:HAVING子句必须写在GROUP BY子句之后
将 HAVING 子句用于对聚合结果进行过滤,并对学生表和成绩表进行了连接。
ORDER BY排序
[ ORDER BY… ] #指定查询记录按一个或者多个条件排序
ORDER BY排序查询:对SELECT语句查询得到的结果,按某些字段进行排序,与DESC(降序)或ASC(升序)搭配使用,默认为ASC(升序)。
SELECT column_name,column_name
FROM table_name
ORDER BY column_name,column_name ASC|DESC;
ORDER BY 关键字默认按照「升序」对返回的结果集进行排序。如果需要按照「降序」对记录进行排序,可以使用 DESC 关键字。
LIMIT限制
[ LIMIT { [ offset,] row_count | row_count OFFSET offset }] ; #指定查询的记录从哪条至哪条
LIMIT [m,]n 或 LIMIT n OFFSET m
-
限制SELECT返回结果的行数
-
m 制定第一个返回记录行的偏移量
-
n 制定返回记录行的最大数目
m不指定则偏移量为0,从第一条开始返回前n条记录LIMIT 常用于分页显示
SELECT * FROM `result` LIMIT 5 #返回前5条记录(1-5)
SELECT * FROM `result` LIMIT 5,10 #返回6-15条记录(1-10->6-15)
子查询
在查询语句中的WHERE条件子句中,又嵌套了另外一个查询语句
嵌套查询可由多个子查询组成,求解的方式是由里及外子查询返回的结果一般都是集合,故而建议使用 IN 关键字
MySQL函数
-
数学函数
-
字符串函数
-
日期和时间函数
-
系统信息函数
统计函数:
函数名称 | 描述 |
---|---|
COUNT( ) | 返回满足SELECT条件的记录总和数,如 SELECT COUNT(*)… |
SUM( ) | 返回数字字段或表达式列作统计,返回一列的总和 |
AVG( ) | 通常为数值字段或表达列作统计,返回一列的平均值 |
MAX( ) | 可以为数值字段、字符字段或表达式列作统计,返回最大的值 |
MIN( ) | 可以为数值字段、字符字段或表达式列作统计,返回最小的值 |
查询本月过生日的学生:
SELECT *
FROM student
WHERE MONTH(s_birth) = MONTH(CURDATE());
MySQL 为日期增加一个时间间隔:date_add()
set @dt = now();
select date_add(@dt, interval 1 day); -- add 1 day
select date_add(@dt, interval 1 hour); -- add 1 hour
select date_add(@dt, interval 1 minute); -- ...
select date_add(@dt, interval 1 second);
select date_add(@dt, interval 1 microsecond);
select date_add(@dt, interval 1 week);
select date_add(@dt, interval 1 month);
select date_add(@dt, interval 1 quarter);
select date_add(@dt, interval 1 year);
select date_add(@dt, interval -1 day); -- sub 1 day
#周一是0 sql中周一到周日 分别对应0-6
select weekday(now());
-- 0
select date_sub(CURDATE(), INTERVAL weekday(now()) day);
#表示本周周一日期
-- 2024-07-29
select date_add(now(), INTERVAL 6 - weekday(now()) day);
#表示本周周日时间
-- 2024-08-04 17:40:00
select date_add(now(),interval 7 - weekday(now()) day);
#表示下周周一时间
-- 2024-08-05 17:40:59
select date_add(now(),interval 13 - weekday(now())day);
#表示下周周日时间
-- 2024-08-11 17:44:42
select concat(year(now()),'-',month(now()),'-',day(now())); #时间拼接
-- 2024-7-31
select date(concat(year(now()), '-', month(now()), '-', day(now()))
#拼接后注意转换类型
-- 2024-7-31
表合并UNION
CREATE TABLE fzh
select * from fz1
UNION ALL
select * from fz2
UNION与UNION ALL的区别: 1、对重复结果的处理:UNION在进行表链接后会去重,UNION All不会。
2、对排序的处理:Union将会按照字段的顺序进行排序;UNION ALL只是简单的将两个结果合并后就返回。
UNION ALL 要比UNION效率高,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序时的话,那么就使用UNION ALL。