美文网首页Ping说MySQL
MySQL之DQL查询数据

MySQL之DQL查询数据

作者: Ping开源 | 来源:发表于2020-11-29 00:04 被阅读0次

    四、DQL查询数据

    1.DQL(Data Query Language):数据查询语言

    所有的查询操作都要用它 Select。
    简单的查询,复杂的查询它都能做。
    是数据库中最核心的语言,最重要的语句;
    也是使用频率最高的语句。
    school测试数据库及grade、result、student、subject表的创建及添加数据的代码,可下载使用:https://share.weiyun.com/4QiyVQfd,也可以直接复制下方。

    -- 创建一个school数据库
    create database if not exists `school`;
    use `school`;
    -- 创建学生表
    drop table if exists `student`;
    create table `student`(
      `StudentNo` int(4) not null comment '学号',
      `LoginPwd` varchar(20) default null,
      `StudentName` varchar(20) default null comment '学生姓名',
      `sex` tinyint(1) default null comment '性别,0或1',
      `GradeId` int(11) default null comment '年级编号',
      `phone` varchar(50) not null comment '联系电话,允许为空',
      `address` varchar(255) not null comment '地址,允许为空',
      `BornDate` datetime default null comment '出生时间',
      `email` varchar (50) not null comment '邮箱账号,允许为空',
      `IdentityCard` varchar(18) default null comment '身份证号',
      primary key (`StudentNo`),
      unique key `identitycard`(`IdentityCard`),
      key `email` (`email`)
    )engine=myisam default charset=utf8;
    
    -- 创建年级表
    drop table if exists `grade`;
    create table `grade`(
      `GradeId` int(11) not null auto_increment comment '年级编号',
      `GradeName` varchar(50) not null comment '年级名称',
      primary key (`GradeId`)
    ) engine=innodb auto_increment = 6 default charset = utf8;
    
    -- 创建科目表
    drop table if exists `subject`;
    create table `subject`(
      `SubjectNo`int(11) not null auto_increment comment '课程编号',
      `SubjectName` varchar(50) default null comment '课程名称',
      `ClassHour` int(4) default null comment '学时',
      `GradeId` int(4) default null comment '年级编号',
      primary key (`SubjectNo`)
    )engine = innodb auto_increment = 19 default charset = utf8;
    
    -- 创建成绩表
    drop table if exists `result`;
    create table `result`(
      `StudentNo` int(4) not null comment '学号',
      `SubjectNo` int(4) not null comment '课程编号',
      `ExamDate` datetime not null comment '考试日期',
      `StudentResult` int (4) not null comment '考试成绩',
      key `SubjectNo` (`SubjectNo`)
    )engine = innodb default charset = utf8;
    
    -- 插入学生数据( 这里只添加了2行,其余自行添加)
    insert into `student` (`StudentNo`,`LoginPwd`,`StudentName`,`sex`,`GradeId`,`phone`,`address`,`BornDate`,`email`,`IdentityCard`)
    values(1000,'123456','张伟',0,2,'13800001234','北京朝阳','1980-1-1','text123@qq.com','123456198001011234'),
    (1001,'123456','赵强',1,3,'13800002222','广东深圳','1990-1-1','text111@qq.com','123456199001011233');
    
    -- 插入成绩数据 (这里仅插入了一组,其余自行添加)
    insert into `result`(`StudentNo`,`SubjectNo`,`ExamDate`,`StudentResult`)
    values(1000,1,'2013-11-11 16:00:00',85),
    (1000,2,'2013-11-12 16:00:00',70),
    (1000,3,'2013-11-11 09:00:00',68),
    (1000,4,'2013-11-13 16:00:00',98),
    (1000,5,'2013-11-14 16:00:00',58);
    
    -- 插入年级数据
    insert into `grade` (`GradeId`,`GradeName`) values(1,'大一'),(2,'大二'),(3,'大三'),(4,'大四'),(5,'预科班');
    
    -- 插入科目数据
    insert into `subject`(`SubjectNo`,`SubjectName`,`ClassHour`,`GradeId`) values(1,'高等数学-1',110,1),
    (2,'高等数学-2',110,2),
    (3,'高等数学-3',100,3),
    (4,'高等数学-4',130,4),
    (5,'C语言-1',110,1),
    (6,'C语言-2',110,2),
    (7,'C语言-3',100,3),
    (8,'C语言-4',130,4),
    (9,'Java程序设计-1',110,1),
    (10,'Java程序设计-2',110,2),
    (11,'Java程序设计-3',100,3),
    (12,'Java程序设计-4',130,4),
    (13,'数据库结构-1',110,1),
    (14,'数据库结构-2',110,2),
    (15,'数据库结构-3',100,3),
    (16,'数据库结构-4',130,4),
    (17,'C#基础',130,1);
    

    2.指定查询字段

    1)语法:

    SELECT 字段1,字段2,… FROM 表
    

    --查询学术表的全部信息
    SELECT * FROM student
    --查询表中的指定字段
    SELECT `StudentNo`,`StudentName` FROM student
    --用AS给结果取别名
    SELECT `StudentNo`AS 学号,`StudentName` AS 学生姓名 FROM student AS 学生表
    --运用函数 Concat(a,b)
    SELECT Concat('姓名',StudentName) AS 新名字 FROM student
    

    有的时候,列名字不是那么见名知意,可以用AS起别名:字段名/表名 as 别名。
    2)去重:distinct
    作用:去除SELECT查询出来的结果中重复的数据,重复的数据只显示一条。
    例:查询参加考试的同学及其成绩。

    SELECT * FROM result --查询全部的考试成绩
    SELECT `StudentNo` FROM result --查询参加考试的同学
    SELECT DISTINCT `StudentNo` FROM result --查询参加考试的同学,去除重复的数据
    

    3)数据库的列(表达式)

    SELECT VERSION() --查询系统版本(函数)
    SELECT 100*3-1 AS 计算结果 --用来计算(表达式)
    SELECT @@auto_increment_increment --查询自增步数(变量)
    --使学生的考试成绩+1
    SELECT `StudentNo`,`StudentResult`+1 AS '提分后' FORM result
    

    数据库中的表达式:文本值、列、NULL、函数、计算表达式、系统变量······
    语法:

    select 表达式 from 表
    

    3.where 条件子句

    作用:检索数据中符合条件的值。
    搜索的条件由一个或多个表达式组成,结果为布尔值。
    1)逻辑运算符

    运算符 语法 描述
    and && a and b a&&b 逻辑与,两个都为真,结果为真。
    or a or b 逻辑或,其中一个为真,则结果为真。
    Not ! not a !a 逻辑非,真为假,假为真。

    注:or也可以用两个|来表示,尽量使用英文字母而不是符号。

    --查询考试成绩在95-100之间的学生学号
    SELECT StudentNo,`StudentResult` FROM result
    WHERE StudentResult>=95 AND StudentResult<=100
    --模糊查询(区间)
    SELECT StudentNo,`StudentResult` FROM result
    WHERE StudentResult BETWEEN 95 AND 100
    --除了1000号学生之外的同学成绩
    SELECT StudentNo,`StudentResult` FROM result
    WHERE NOT StudentNo=1000
    

    2)模糊查询:比较运算符

    运算符 语法 描述
    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,…) 假设a在a1或a2或…其中的某一个值中,结果为真

    --查询姓刘的同学
    --与like结合,%代表0到任意个字符,_代表一个字符
    SELECT `StudentNo`,`StudentName` FROM `student`
    WHERE StudentName LIKE '刘%'
    --查询姓刘的同学,名字后面只有一个字的
    SELECT `StudentNo`,`StudentName` FROM `student`
    WHERE StudentName LIKE '刘_'
    --查询姓刘的同学,名字后面有两个字的
    SELECT `StudentNo`,`StudentName` FROM `student`
    WHERE StudentName LIKE '刘__'
    --查询姓名中有嘉字的同学
    SELECT `StudentNo`,`StudentName` FROM `student`
    WHERE StudentName LIKE '%嘉%'
    --in用于查询具体的一个或多个值
    --查询1001,1002,1003号学生
    SELECT `StudentNo`,`StudentName` FROM `student`
    WHERE StudentNo IN (1001,1002,1003);
    --查询地址为空的同学
    SELECT `StudentNo`,`StudentName` FROM `student`
    WHERE address=' ' OR address IS NULL
    --查询没有出生日期的同学
    SELECT `StudentNo`,`StudentName` FROM `student`
    WHERE `BornDate` IS NOT NULL
    

    4.联表查询

    1)JOIN对比

    SQL JOIN图示总结

    百度搜索七种join理论

    七种JOIN理论
    例:查询参加了考试的同学(学号、姓名、科目编号、分数)。
    思路:Ⅰ分析需求,分析查询的字段来自哪些表(连接查询)。
    Ⅱ确定使用哪种查询。共7种
    确定交叉点(student和result这两个表中哪个数据是相同的)。
    判断的条件:学生表中的StudentNo = 成绩表中的StudentNo。
    --Inner Join
    SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
    FROM student s
    INNER JOIN result r
    ON s.StudentNo = r.StudentNo
    --Right Join
    SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
    FROM student s
    RIGHT JOIN result r
    ON s.StudentNo = r.StudentNo
    --Left Join
    SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
    FROM student s
    LEFT JOIN result r
    ON s.StudentNo = r.StudentNo
    

    注:有时使用AS可省略。

    操作 描述
    Inner join 如果表中至少有一个匹配,就返回匹配的值。
    left join 会从左表中返回所有的值,即使右表中没有匹配。
    right join 会从右表中返回所有的值,即使左表中没有匹配。

    例:查询缺考的同学。

    SELECT s.StudentNo,StudentName,SubjectNo,StudentResult
    FROM student s
    LEFT JOIN result r
    ON s.StudentNo = r.StudentNo
    WHERE StudentResult IS NULL
    

    on与where:
    join (连接的表) on (判断的条件):连接查询
    where:等值查询

    思考题:查询了参加考试的同学信息(学号、学生姓名、科目名、分数)。
    SELECT s.StudentNo,StudentName,SubjectName,`StudentResult`
    FROM student
    RIGHT JOIN result r
    ON r.SttudentNo = s.StudentNo
    INNER JOIN `subject` sub
    ON r.SubjectNo = sub.SubjectNo
    

    总结:Ⅰ要查询哪些数据。select…
    Ⅱ从哪几个表中查。FROM 表 XXX Join 连接的表 on 交叉条件
    Ⅲ假设存在一种多张表查询,先查询两张表然后再慢慢增加。
    2)自连接
    school数据库中的分类表category的创建和导入数据的代码,可下载使用:https://share.weiyun.com/Wp0LerVu,也可以直接复制下方。

    CREATE TABLE `category` ( 
      `categoryId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主题id', 
      `pid`  INT(10) NOT NULL COMMENT  '父id', 
      `categoryName`  VARCHAR(50) NOT NULL COMMENT '主题名字', 
      PRIMARY KEY (`categoryId`) 
    ) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; 
    
    INSERT INTO `category` (`categoryId`, `pid`, `categoryName`) 
    VALUES ('2', '1', '信息技术'),
    ('3', '1', '软件开发'),
    ('5', '1', '美术设计'),
    ('4', '3', '数据库'),
    ('8', '2', '办公信息'),
    ('6', '3', 'web开发'),
    ('7', '5', 'ps技术');
    
    上面代码执行结果

    自己的表和自己的表连接,核心:一张表拆为两张一样的表即可。
    父表:

    categoryId categoryName
    2 信息技术
    3 软件开发
    5 美术设计

    子表:

    pid categoryId categoryName
    3 4 数据库
    2 8 办公信息
    3 6 web开发
    5 7 ps技术

    操作:查询父类对应的子类关系。

    --查询父子信息:把一张表看成两个一模一样的表
    SELECT a.`categoryName` AS '父栏目',b.`categoryName` AS '子栏目'
    FROM `category` AS a,`category` AS b
    WHERE a.`categoryId` = b.`pid`
    

    结果表的样式:

    父类 子类
    信息技术 办公信息
    软件开发 数据库
    软件开发 web开发
    美术设计 ps技术

    3)联表查询练习
    ①查询科目所属的年级(科目名称、年级名称)。

    SELECT `SubjectName`,`GradeName`
    FROM `subject` sub
    INNER JOIN `grade` g
    ON sub.`GradeId` = g.`GradeId`
    

    ②查询学员所属的年级(学号、学生姓名、年级名称)。

    SELECT StudentNo,StudentName,`GradeName`
    FROM student s
    INNER JOIN `grade` g
    ON s.`GradeId` = g.`GradeId`
    
    思考题改:查询参加了数据库结构-1考试的学生信息(学号、学生姓名、科目名、分数)。
    SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
    FROM student s
    INNER JOIN `result` r
    ON s.StudentNo = r.StudentNo
    INNER JOIN `subject` sub
    ON r.`SubjectNo` = sub.`SubjectNo`
    WHERE SubjectName = '数据库结构-1'
    

    5.分页和排序

    1)排序
    方式:升序ASC,降序DESC。
    语法:

    ORDER BY 通过哪个字段排序,排序方式
    

    例:以上例思考题改为基础,将查询的信息按成绩排序。

    SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
    FROM student s
    INNER JOIN `result` r
    ON s.StudentNo = r.StudentNo
    INNER JOIN `subject` sub
    ON r.`SubjectNo` = sub.`SubjectNo`
    WHERE SubjectName = '数据库结构-1'
    ORDER BY StudentResult ASC
    

    1)分页
    分页的原因:缓解数据库的压力,给用户的体验更好。用瀑布流的话可以不分页。
    语法:

    limit 起始值,页面的大小
    

    例:以上例思考题改为基础,页面大小为5,显示第一页的内容。

    SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
    FROM student s
    INNER JOIN `result` r
    ON s.StudentNo = r.StudentNo
    INNER JOIN `subject` sub
    ON r.`SubjectNo` = sub.`SubjectNo`
    WHERE SubjectName = '数据库结构-1'
    ORDER BY StudentResult ASC
    LIMIT 0,5
    

    网页应用显示:当前页,总的页数,页面的大小
    公式:ⅠpageSize:页面大小
    Ⅱ(n-1)*pageSize:初始值
    Ⅲn:当前页 = 数据总数/页面大小

    思考题:查询JAVA第一学年课程成绩排名前十,并且分数要大于80的学生信息(学号、姓名、课程名称、分数)。
    SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
    FROM student s
    INNER JOIN `result` r
    ON s.StudentNo = r.StudentNo
    INNER JOIN `subject` sub
    ON sub.`SubjectNo` = r.`SubjectNo`
    WHERE SubjectName = 'JAVA第一学年' AND StudentResult>=80
    ORDER BY StudentResult DESC
    LIMIT 0,10
    

    6.子查询

    where(这个值是计算出来的)
    本质:在where语句中嵌套一个子查询语句。
    例:查询数据库结构-1的所有考试结果(学号、科目编号、成绩),降序排列。
    方式一:使用查询连接

    SELECT `StudentNo`,r.`SubjectNo`,`StudentResult`
    FROM `result` r
    INNER JOIN `subject` sub
    ON  r.SubjectNo = sub.SubjectNo
    WHERE SubjectName = '数据库结构-1'
    ORDER BY StudentResult DESC
    

    方式二:使用子查询(由里及外)

    SELECT `StudentNo`,r.`SubjectNo`,`StudentResult`
    FROM `result` 
    WHERE SubjectNo = (
      SELECT SubjectNo FROM `subject`
      WHERE SubjectName = '数据库结构-1'
    )
    ORDER BY StudentResult DESC
    

    例:查询课程为高等数学-2且分数不小于80的同学的学号和姓名。
    方式一

    SELECT s.StudentNo,StudentName
    FORM student s
    INNER JOIN result r
    ON s.StuentNo = r.StuentNo
    INNER JOIN `subject` sub
    ON r.`SubjectNo` = sub.`SubjectNo`
    WHERE `StudentName` = '高等数学-2' AND StudentResult>=80
    

    方式二

    SELECT s.`StudentNo`,`StudentName`
    FORM student s
    INNER JOIN result r
    ON r.StuentNo = s.StuentNo
    WHERE `StudentResult`>=80 AND `SubjectNo` = (
      SELECT SubjectNo FROM `subject`
      WHERE `SubjectName` = '高等数学-2'                                                                                                                                                                    
    )
    --进一步改变
    SELECT s.StudentNo,StudentName FORM student WHERE StudentNo IN (
      SELECT StudentNo FROM result WHERE StudentResult>=80 AND SubjectNo = (
        SELECT SubjectNo FROM `subject` WHERE `SubjectName` = '高等数学-2'
      )
    )
    

    练习:查询C语言-1课程中前5名同学的成绩信息(学号、姓名、分数)。
    SELECT完整语法总结

    SELECT [ALL | DISTINCT]
    {* | table.* | [table.field1[as alias1] [,table.field2[as alias2]] [,…]]}
    FROM table_name [as table_alias]
      [left | right | inner join table_name2] --联合查询
      [WHERE…] --指定结果需满足的条件
      [GROUP BY…] --指定结果按照哪几个字段来分组
      [HAVING] --过滤分组的记录必须满足的次要条件
      [ORDER BY…] --指定查询记录按一个或多个条件排序
      [LIMIT {[offest.] row_count | row_countOFFEST offset}]
      --指定查询的记录从哪条至哪条
    

    注:[]括号代表可选的,{}括号代表必选的。

    相关文章

      网友评论

        本文标题:MySQL之DQL查询数据

        本文链接:https://www.haomeiwen.com/subject/fyqcwktx.html