DQL语句

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


  • 查询数据库数据 , 如SELECT语句
  • 简单的单表查询或多表的复杂查询和嵌套查询
  • 是数据库语言中最核心,最重要的语句
  • 使用频率最高的语句


SELECT语法

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

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

指定查询字段

  1. -- 查询表中所有的数据列结果 , 采用 **" \* "** 符号; 但是效率低,不推荐 .
  2. -- 查询所有学生信息
  3. SELECT * FROM student;
  4. -- 查询指定列(学号 , 姓名)
  5. SELECT studentno,studentname FROM student;

AS 子句作为别名

作用:

  • 可给数据列取一个新别名
  • 可给表取一个新别名
  • 可把经计算或总结的结果用另一个新名称来代替
    ```sql — 这里是为列取别名(当然as关键词可以省略) SELECT studentno AS 学号,studentname AS 姓名 FROM student;

— 使用as也可以为表取别名 SELECT studentno AS 学号,studentname AS 姓名 FROM student AS s;

— 使用as,为查询结果取一个新名字 — CONCAT()函数拼接字符串 SELECT CONCAT(‘姓名:’,studentname) AS 新姓名 FROM student;

  1. DISTINCT关键字的使用
  2. 作用 : 去掉SELECT查询返回的记录结果中重复的记录 ( 返回所有列的值都相同 ) , 只返回一条
  3. ```sql
  4. -- # 查看哪些同学参加了考试(学号) 去除重复项
  5. SELECT * FROM result; -- 查看考试成绩
  6. SELECT studentno FROM result; -- 查看哪些同学参加了考试
  7. SELECT DISTINCT studentno FROM result; -- 了解:DISTINCT 去除重复项 , (默认是ALL)

where条件语句

作用:用于检索数据表中 符合条件 的记录
搜索条件可由一个或多个逻辑表达式组成 , 结果一般为真或假.

逻辑操作符

操作符名称 语法
and 或 && a and b 或 a && b
or 或 | | a or b 或 a b
not 或! not a 或者 !a


测试

  1. -- 满足条件的查询(where)
  2. SELECT Studentno,StudentResult FROM result;
  3. -- 查询考试成绩在95-100之间的
  4. SELECT Studentno,StudentResult
  5. FROM result
  6. WHERE StudentResult>=95 AND StudentResult<=100;
  7. -- AND也可以写成 &&
  8. SELECT Studentno,StudentResult
  9. FROM result
  10. WHERE StudentResult>=95 && StudentResult<=100;
  11. -- 模糊查询(对应的词:精确查询)
  12. SELECT Studentno,StudentResult
  13. FROM result
  14. WHERE StudentResult BETWEEN 95 AND 100;
  15. -- 除了1000号同学,要其他同学的成绩
  16. SELECT studentno,studentresult
  17. FROM result
  18. WHERE studentno!=1000;
  19. -- 使用NOT
  20. SELECT studentno,studentresult
  21. FROM result
  22. WHERE NOT studentno=1000;

模糊查询 :比较操作符

操作符名称 语法
is null 字段 is null
is not null 字段 is not null
bewten where 字段 betwen xx and xx
like where 字段 like%
in where 字段 in(x,xx)

注意:

  • 数值数据类型的记录之间才能进行算术运算 ;
  • 相同数据类型的数据之间才能进行比较 ;

测试:

  1. -- 模糊查询 between and \ like \ in \ null
  2. -- =============================================
  3. -- LIKE
  4. -- =============================================
  5. -- 查询姓刘的同学的学号及姓名
  6. -- like结合使用的通配符 : % (代表0到任意个字符) _ (一个字符)
  7. SELECT studentno,studentname FROM student
  8. WHERE studentname LIKE '刘%';
  9. -- 查询姓刘的同学,后面只有一个字的
  10. SELECT studentno,studentname FROM student
  11. WHERE studentname LIKE '刘_';
  12. -- 查询姓刘的同学,后面只有两个字的
  13. SELECT studentno,studentname FROM student
  14. WHERE studentname LIKE '刘__';
  15. -- 查询姓名中含有 字的
  16. SELECT studentno,studentname FROM student
  17. WHERE studentname LIKE '%嘉%';
  18. -- 查询姓名中含有特殊字符的需要使用转义符号 '\'
  19. -- 自定义转义符关键字: ESCAPE ':'
  20. -- =============================================
  21. -- IN
  22. -- =============================================
  23. -- 查询学号为1000,1001,1002的学生姓名
  24. SELECT studentno,studentname FROM student
  25. WHERE studentno IN (1000,1001,1002);
  26. -- 查询地址在北京,南京,河南洛阳的学生
  27. SELECT studentno,studentname,address FROM student
  28. WHERE address IN ('北京','南京','河南洛阳');
  29. -- =============================================
  30. -- NULL 空
  31. -- =============================================
  32. -- 查询出生日期没有填写的同学
  33. -- 不能直接写=NULL , 这是代表错误的 , 用 is null
  34. SELECT studentname FROM student
  35. WHERE BornDate IS NULL;
  36. -- 查询出生日期填写的同学
  37. SELECT studentname FROM student
  38. WHERE BornDate IS NOT NULL;
  39. -- 查询没有写家庭住址的同学(空字符串不等于null)
  40. SELECT studentname FROM student
  41. WHERE Address='' OR Address IS NULL;

连接查询

JOIN 对比

操作符名称 描述
inner join 取两个表的交集
left join 即使右表没有匹配数据,也返回左边的行
right join 即使左表没有匹配数据,也返回右边的行

七种关联查询
mysql 第四节 - 图1

案例

以一个简易问答系统为例,包括问题表和问题所属标签

问题表如下:

  1. CREATE TABLE `t_qa` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3. `title` varchar(200) NOT NULL DEFAULT '' COMMENT '标题',
  4. `answer_count` int(5) unsigned NOT NULL DEFAULT '0' COMMENT '回答个数',
  5. `label_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '标签id',
  6. `create_by` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '创建人',
  7. `create_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间',
  8. `update_by` bigint(20) unsigned DEFAULT NULL COMMENT '更新人',
  9. `update_date` datetime DEFAULT NULL COMMENT '更新时间',
  10. `del_flag` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0:不删除,1:删除',
  11. PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  13. INSERT INTO `t_qa` (`id`, `title`, `answer_count`, `label_id`, `create_by`, `create_date`, `update_by`, `update_date`, `del_flag`)
  14. VALUES
  15. (1, 'Java是什么?', 5, 1, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  16. (2, 'PHP是什么?', 4, 2, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  17. (3, '前端是什么?', 3, 3, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  18. (4, 'nodejs是什么?', 2, 0, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  19. (5, 'css是什么?', 1, 0, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  20. (6, 'JavaScript是什么?', 0, 0, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0);

标签表如下:

  1. CREATE TABLE `t_label` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3. `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
  4. `create_by` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '创建人',
  5. `create_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间',
  6. `update_by` bigint(20) unsigned DEFAULT NULL COMMENT '更新人',
  7. `update_date` datetime DEFAULT NULL COMMENT '更新时间',
  8. `del_flag` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0:不删除,1:删除',
  9. PRIMARY KEY (`id`)
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  11. INSERT INTO `t_label` (`id`, `name`, `create_by`, `create_date`, `update_by`, `update_date`, `del_flag`)
  12. VALUES
  13. (1, 'java', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  14. (2, 'php', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  15. (3, '大前端', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  16. (4, 'mybatis', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  17. (5, 'python', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0),
  18. (6, '多线程', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0);


一、左连接(LEFT JOIN)

image.png

查询结果:

问题 回答个数 标签id 标签名称
Java是什么? 5 1 java
PHP是什么? 4 2 php
前端是什么? 3 3 大前端
nodejs是什么? 2 NULL NULL
css是什么? 1 NULL NULL
JavaScript是什么? 1 NULL NULL

sql:

  1. SELECT
  2. tq.title, tq.answer_count, tl.id, tl.name
  3. FROM
  4. t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id

二、右连接(RIGHT JOIN)

image.png

查询结果:

问题 回答个数 标签id 标签名称
Java是什么? 5 1 java
PHP是什么? 4 2 php
前端是什么? 3 3 大前端
NULL NULL 4 mybatis
NULL NULL 5 python
NULL NULL 6 多线程

sql:

  1. SELECT
  2. tq.title, tq.answer_count, tl.id, tl.name
  3. FROM
  4. t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id

三、内连接(INNER JOIN)


image.png

查询结果:

问题 回答个数 标签id 标签名称
Java是什么? 5 1 java
PHP是什么? 4 2 php
前端是什么? 3 3 大前端

sql语句:

  1. SELECT
  2. tq.title, tq.answer_count, tl.id, tl.name
  3. FROM
  4. t_qa tq INNER JOIN t_label tl ON tq.label_id = tl.id

四、左独有连接(LEFT JOIN)


image.png

查询结果:

问题 回答个数 标签id 标签名称
nodejs是什么? 2 NULL NULL
css是什么? 1 NULL NULL
JavaScript是什么? 0 NULL NULL
  1. SELECT
  2. tq.title, tq.answer_count, tl.id, tl.name
  3. FROM
  4. t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id
  5. WHERE
  6. tl.id IS NULL

五、右独有连接(RIGHT JOIN)

image.png
查询结果:

问题 回答个数 标签id 标签名称
NULL NULL 4 mybatis
NULL NULL 5 python
NULL NULL 6 多线程

sql:

  1. SELECT
  2. tq.title, tq.answer_count, tl.id, tl.name
  3. FROM
  4. t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id
  5. WHERE
  6. tq.label_id IS NULL

六、全连接(FULL JOIN)


image.png

由于MySQL不支持FULL OUTER JOIN,所以如果有全连接需求时,可用表达式:full outer join = left outer join UNION right outer join来实现。

UNION 和 UNION ALL 操作符

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意:UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

SQL UNION 语法

  1. SELECT column_name(s) FROM table_name1
  2. UNION
  3. SELECT column_name(s) FROM table_name2

注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。


SQL UNION ALL 语法

  1. SELECT column_name(s) FROM table_name1
  2. UNION ALL
  3. SELECT column_name(s) FROM table_name2

另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。

问题 回答个数 标签id 标签名称
Java是什么? 5 1 java
PHP是什么? 4 2 php
前端是什么? 3 3 大前端
nodejs是什么? 2 NULL NULL
css是什么? 1 NULL NULL
JavaScript是什么? 0 NULL NULL
NULL NULL 4 mybatis
NULL NULL 5 python
NULL NULL 6 多线程

sql:

  1. SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id
  2. UNION
  3. SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id

七、全连接去交集(FULL JOIN)


image.png
结果

问题 回答个数 标签id 标签名称
nodejs是什么? 2 NULL NULL
css是什么? 1 NULL NULL
JavaScript是什么? 0 NULL NULL
NULL NULL 4 mybatis
NULL NULL 5 python
NULL NULL 6 多线程

SQL:

  1. SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id WHERE tl.id IS NULL
  2. UNION
  3. SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id WHERE tq.label_id IS NULL

排序和分页

排序

语法 : ORDER BY

  1. ORDER BY 语句用于根据指定的列对结果集进行排序。
  2. ORDER BY 语句默认按照ASC升序对记录进行排序。
  3. 如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。

— 查询 数据库结构-1 的所有考试结果(学号 学生姓名 科目名称 成绩)

  1. -- 按成绩降序排序
  2. SELECT s.studentno,studentname,subjectname,StudentResult
  3. FROM student s
  4. INNER JOIN result r
  5. ON r.studentno = s.studentno
  6. INNER JOIN `subject` sub
  7. ON r.subjectno = sub.subjectno
  8. WHERE subjectname='数据库结构-1'
  9. ORDER BY StudentResult DESC


分页

语法 :
好处 : (用户体验,网络传输,查询压力)

  1. SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset

推导:
第一页 : limit 0,5
第二页 : limit 5,5
第三页 : limit 10,5

……
第N页 : limit (pageNo-1)*pageSzie,pageSzie
[pageNo:页码, pageSize:单页面显示条数

— 每页显示5条数据

  1. SELECT s.studentno,studentname,subjectname,StudentResult
  2. FROM student s
  3. INNER JOIN result r
  4. ON r.studentno = s.studentno
  5. INNER JOIN `subject` sub
  6. ON r.subjectno = sub.subjectno
  7. WHERE subjectname='数据库结构-1'
  8. ORDER BY StudentResult DESC , studentno
  9. LIMIT 0,5

— 查询 JAVA第一学年 课程成绩前10名并且分数大于80的学生信息(学号,姓名,课程名,分数)

  1. SELECT s.studentno,studentname,subjectname,StudentResult
  2. FROM student s
  3. INNER JOIN result r
  4. ON r.studentno = s.studentno
  5. INNER JOIN `subject` sub
  6. ON r.subjectno = sub.subjectno
  7. WHERE subjectname='JAVA第一学年'
  8. ORDER BY StudentResult DESC
  9. LIMIT 0,10


子查询

什么是子查询?

在查询语句中的WHERE条件子句中,又嵌套了另一个查询语句 嵌套查询可由多个子查询组成,求解的方式是由里及外; 子查询返回的结果一般都是集合,故而建议使用IN关键字;

有三张表分别如下:

  1. customers: 存储顾客信息 | cust_id | cust_name | cust_city | cust_country | csut_email | | —- | —- | —- | —- | —- | | 1001 | test01 | 广州 | 中国 | 11@qq.com | | 1002 | test02 | 深圳 | 中国 | 21@qq.com | | 1003 | test03 | 上海 | 中国 | 23@qq.com | | 1004 | test04 | 北京 | 中国 | 25@qq.com | | 1005 | test05 | 长沙 | 中国 | 26@qq.com | | 1006 | test06 | 纽约 | 美国 | 123@163.com |


2. orderitems:只存储订单信息,无客户信息

order_num prod_id quantity item_price
201901 TNT1 1 1000
201902 TNT2 2 2000
201903 TNT3 3 3000


3.orders:存储订单号和顾客id

order_num cust_id
201901 1001
201902 1002
201903 1003

注意:一般在子查询中,程序先运行在嵌套在最内层的语句,再运行外层。因此在写子查询语句时,可以先测试下内层的子查询语句是否输出了想要的内容,再一层层往外测试,增加子查询正确率。否则多层的嵌套使语句可读性很低。

子查询训练

训练1:
查询买了商品为’TNT2’的顾客信息

子查询中涉及3张表的订单。因此分三步,1. 在orderitems里找出TNT2的订单号;2. 在orders里找出第一步找出的订单号对应的客户id;3. 在customers中找出第二步对应客户的所有信息。

  1. -- 1. orderitems里找出TNT2的订单号
  2. SELECT order_num FROM orderitems WHERE prod_id='TNT2';
  3. -- 2. orders里找出第一步找出的订单号对应的客户id
  4. SELECT cust_id FROM orders
  5. WHERE order_num
  6. IN (SELECT order_num FROM orderitems WHERE prod_id='TNT2');
  7. --3. customers中找出第二步对应客户的所有信息
  8. SELECT * FROM customers
  9. WHERE cust_id
  10. IN (SELECT cust_id FROM orders WHERE order_num IN
  11. (SELECT order_num FROM orderitems WHERE prod_id='TNT2'));

子查询一般与IN操作符结合使用,也可用=><等。

子查询还可以用于计算字段。

如,想要查询每个客户的订单数

分步思考:1. 查询某个客户的订单数;2. 某个客户改为所有客户。