目录
第1关:内连接查询
任务描述
本关任务:使用内连接查询数据表中学生姓名和对应的班级。
相关知识
为了完成本关任务,你需要掌握: 1.什么是内连接查询; 2.如何使用内连接查询。
内连接查询
-
仅将两个表中满足连接条件的行组合起来作为结果集,称为内连接;
-
关键字:
[inner] join ... on。
语法:
表1 [inner] join 表2 on 表1.字段=表2.字段
语法解释:
从表1中取出每一条记录,去表2中与所有的记录进行匹配,匹配必须是某个条件在表1中与表2中相同,最终才会保留结果,否则不保留。inner 关键字可省略不写;on 表示连接条件:条件字段就是代表相同的业务含义(如下面两张表中的 employee.dept_id 和 department.id),大多数情况下为两张表中的主外键关系。
内连接查询的使用
现在我们有两张表,数据如下: employee表数据:
| id | name | dept_id |
|---|---|---|
| 1 | Nancy | 4 |
| 2 | Tod | 2 |
| 3 | Carly | 1 |
| 4 | Allen | 2 |
| 5 | Mary | (null) |
department表数据:
| id | name |
|---|---|
| 1 | 开发部 |
| 2 | 测试部 |
| 3 | 运维部 |
| 4 | 销售部 |
现在想要查询出员工姓名以及其对应的部门名称,我们就使用内连接来进行查询。
- 我们可以将关联查询思路分为三步:
1.确定所连接的表, 2.确定所要查询的字段, 3.确定连接条件与连接方式。 示例:
select emp.name as empname,dept.name as deptname from department as dept inner join employee as amp on dept.id=emp.dept_id;
结果:
| empname | deptname |
|---|---|
| Carly | 开发部 |
| Tod | 测试部 |
| Allen | 测试部 |
| Nancy | 销售部 |
其中,没有部门的员工和部门没有员工的部门都没有被查出来,这就是内连接的特点,只查询在连接表中有对应的记录,其中dept.id=emp.dept_id是连接条件。
编程要求
在右侧编辑器补充代码,查询数据表中学生姓名以及对应的班级名称,将其对应的列名分别另命名为studentName和className。
我们为你提供了两张表,内容如下:
tb_student表数据:
| id | name | class_id |
|---|---|---|
| 1 | Emma | 2 |
| 2 | Mary | 4 |
| 3 | Allen | (null) |
| 4 | Kevin | 1 |
| 5 | Rose | 2 |
| 6 | James | 1 |
tb_class表数据:
| id | name |
|---|---|
| 1 | 软件1631 |
| 2 | 软件1632 |
| 3 | 测试1631 |
| 4 | 测试1632 |
测试说明
平台会对你编写的代码进行测试:
开始你的任务吧,祝你成功!
代码
--########## 查询数据表中学生姓名和对应的班级 ##########
--#请在此处添加实现代码
--########## Begin ##########
select tb_student.name as studentName,tb_class.name as className
from tb_student join tb_class on tb_class.id = tb_student.class_id;
--########## End ##########
第2关:外连接查询
任务描述
本关任务:使用外连接查询数据表中所有班级和对应班级里学生的姓名。
相关知识
为了完成本关任务,你需要掌握: 1.什么是外连接查询; 2.如何使用外连接查询。
外连接查询
-
以某张表为主,取出里面的所有记录,然后每条与另外一张表进行连接,不管能不能匹配上条件,最终都会保留。能匹配,正确保留;不能匹配,其它表的字段都置空(
null),称为外连接。 -
外连接查询分为左外连接查询和右外连接查询;
-
关键字:
left/right [outer] join ... on。
语法:
表1 left/right [outer] join 表2 on 表1.字段=表2.字段
语法解释:
左外连接:在内连接的基础上,还包含表1中所有不符合条件的数据行,并在其中的表2列填写 NULL;右外连接:在内连接的基础上,还包含表2中所有不符合条件的数据行,并在其中的表1列填写 NULL。
外连接查询的使用
我们仍使用如下两张数据表:
employee表数据:
| id | name | dept_id |
|---|---|---|
| 1 | Nancy | 4 |
| 2 | Tod | 2 |
| 3 | Carly | 1 |
| 4 | Allen | 2 |
| 5 | Mary | (null) |
department表数据:
| id | name |
|---|---|
| 1 | 开发部 |
| 2 | 测试部 |
| 3 | 运维部 |
| 4 | 销售部 |
例如查询所有员工姓名以及他所在部门,在内连接中Mary没有被查出,因为他没有对应的部门,现在想把Mary也查出来,就要使用左外连接。

此查询语句以employee为主表查询,因此最终记录至少不少于主表已有的记录数。
- 右外连接是同理的,只是基准表的位置变化了而已。
我们在这里只是将left修改成了right,但是基准表变化了,是以department表的数据去匹配employee表,所以左外连接能做到的查询,右外连接也能做到,仅展现的效果有所不同。
虽然左外连接和右外连接有主表差异,但左外连接和右外连接可以互转,如上面的右外连接也等效于如下查询语句,只需将基准表换一下:
编程要求
在右侧编辑器补充代码,分别使用左外连接和右外连接查询数据表中所有学生姓名和对应的班级名称,查询结果列分别另命名为studentName和className。
1、使用左外连接查询所有学生姓名(学生全部显示,不管有没有班级)和对应的班级 2、使用右外连接查询所有学生姓名和对应的班级(班级全部显示,无论有没有学生)
我们为你提供了两张表,内容如下:
tb_student表数据:
| id | name | class_id |
|---|---|---|
| 1 | Emma | 2 |
| 2 | Mary | 4 |
| 3 | Allen | (null) |
| 4 | Kevin | 1 |
| 5 | Rose | 2 |
| 6 | James | 1 |
tb_class表数据:
| id | name |
|---|---|
| 1 | 软件1631 |
| 2 | 软件1632 |
| 3 | 测试1631 |
| 4 | 测试1632 |
测试说明
平台会对你编写的代码进行测试:
开始你的任务吧,祝你成功!
代码
--########## 使用左外连接查询所有学生姓名(学生全部显示,不管有没有班级)和对应的班级 ##########
--#请在此处添加实现代码
--########## Begin ##########
select tb_student.name as studentName,tb_class.name as className
from tb_class right join tb_student on tb_class.id=tb_student.class_id;
--########## End ##########
--########## 使用右外连接查询所有学生姓名和对应的班级(班级全部显示,无论有没有学生) ##########
--#请在此处添加实现代码
--########## Begin ##########
select tb_student.name as studentName,tb_class.name as className
from tb_class left join tb_student on tb_class.id = tb_student.class_id;
--########## End ##########
第3关:IN、ANY、ALL嵌套子查询
任务描述
本关任务:根据要求使用关键字进行查询。
相关知识
由于列子查询返回的结果集是 N 行一列,因此不能直接使用 = 、>、<、>=、<=、<>这些比较标量结果的操作符。在列子查询中可以使用 ALL、ANY、SOME 和 IN关键字操作符。
为了完成本关任务,你需要掌握:如何在子查询中使用关键字进行查询。
ALL关键字
ALL必须接在一个比较运算符的后面,表示与子查询返回的所有值比较都为 TRUE则返回TRUE。
table1表数据:
| col1 |
|---|
| 2 |
| 10 |
table2表数据:
| col2 |
|---|
| 5 |
| 12 |
| 20 |
举个例子:
SELECT col1 FROM table1 WHERE col1 > ALL (SELECT col2 FROM table2)
该查询语句不会返回任何结果,因为col1中没有比col2所有值都大的值。
ANY和SOME关键字
ANY与比较操作符联合使用,表示与子查询返回的任何值比较为TRUE ,则返回TRUE。 SOME是ANY的别名,一般用的比较少。
仍使用上面二张表的数据:

在子查询中,返回的是table2的所有col2列的结果(5,12,20),然后将table1中col1的值与之进行比较,只要大于col2的任何值则为TRUE,因此查询结果为10。
IN关键字
-
IN的意思就是指定的一个值是否在这个集合中,如果在就返回TRUE;否则就返回FALSE了,同IN(项1,项2,...); -
IN是= ANY的别名,二者相同,但NOT IN的别名却不是<> ANY而是<> SOME。
编程要求
我们为你提供了如下数据表: tb_salary表数据:
| id | position | salary |
|---|---|---|
| 1 | Java | 8000 |
| 2 | Java | 8400 |
| 3 | Java | 9000 |
| 4 | Python | 6500 |
| 5 | Python | 10000 |
根据提供的数据,在右侧编辑器中补充代码:
-
查询薪资表中比
Java最高工资高的所有员工职位名称和薪资; -
查询薪资表中比
Java最低工资高的所有员工职位名称和薪资; -
查询薪资表中职位为
Java的所有员工职位名称和薪资。
测试说明
平台会对你编写的代码进行测试:
开始你的任务吧,祝你成功!
代码
--#请在此处添加实现代码
--########## Begin ##########
--#1.使用 ALL 关键字进行查询
select position,salary
from tb_salary
where salary >(select max(salary) from tb_salary where position ='Java');
--#2.使用 ANY 关键字进行查询
select position,salary
from tb_salary
where salary >(select min(salary) from tb_salary where position='Java');
--#3.使用 IN 关键字进行查询
select position,salary
from tb_salary
where position = 'Java';
--########## End ##########
第4关:分页子查询
任务描述
本关任务:能分页读取表中数据,针对大数据量进行简单优化。
相关知识
为了完成本关任务,你需要掌握:
- 如何根据页数和每页数据量进行分页查询;
- 大数据量级进行优化分页查询。
什么是分页查询
当一个表中有很多符合查询条件的数据的时候,我们往往不需要把他们全部一次性取出来,那样对查询效率或者服务器性能来说都会是一个极大的挑战:例如最简单的商城,假设商城中有一万个数据,但我们在前端可能只会每次看到一页10个左右的数据,当我们浏览完这十个商品后,点击下一页浏览其他的商品,这样的分页浏览,对实际存储商品数据的 OpenGauss 数据库来说,实际上就是使用了 OpenGauss 的分页查询功能。
那么我们该怎么实现分页查询呢?
limit 和 offset 实现的分页查询
limit在之前的学习中已经学习过,它可以返回符合条件的limit条数据:
select * from table where xxx="xxx" limit 10;
输出: 检索记录行符合条件的10条数据
那么我们也可以利用limit和offset来进行分页查询:
select * from table where xxx="xxx" limit 10 offset 10;
输出:检索记录行符合条件的11-20条数据
limit之后的数字代表偏移量,offset代表返回记录的最大值,可以通俗的理解为,从table中取出第limit+1行到limit+offset+1行数据( MySQL 偏移值从0开始计算)。
在实际使用中,我们可以直接把offset直接省略掉:
select * from table where xxx="xxx" limit 10,10;
该语句效果与带offset实际上是一模一样的。
通过分页查询,我们可以精确的定位到行数直接取出符合条件的多条数据,但是这也同样存在着性能问题。
大数据量下分页查询优化
select * from table where xxx="xxx" limit 100,100;select * from table where xxx="xxx" limit 1000,100;select * from table where xxx="xxx" limit 10000,100;select * from table where xxx="xxx" limit 100000,100;select * from table where xxx="xxx" limit 1000000,100;
以上语句在实际使用中实际上查询速度会是越来越慢的,这是因为分页查询方式会从数据库第一条记录开始扫描,所以越往后,查询速度越慢,而且查询的数据越多,也会拖慢总查询速度。
如果可以直接定位到偏移量所在记录,那么查询速度肯定能得到一个巨大的提升,所以可以考虑添加一个嵌套子查询,先查询到偏移量位置,再进行分页:
select * from table where xxx="xxx" andid>=(select id from table where xxx="xxx"limit 100000,1)limit 100;
编程要求
根据提示,在右侧编辑器补充代码:
-
按
prod_id升序查询表products中第6-10行数据,只要求prod_id字段即可(prod_id从1开始); -
利用子查询优化查询出按
prod_id升序的第10-15行数据,只要求prod_id字段即可。 建表语句如下:
create table products(prod_id int PRIMARY KEY,prod_name VARCHAR(30) NOT NULL,prod_price VARCHAR(20));
测试说明
平台会根据表中数据对你的结果进行测试。
代码
--#请在此处添加实现代码
--########## Begin ##########
--#1.分页查询
select prod_id
from products
order by prod_id
limit 5 offset 5;
--#2.用子查询优化分页查询语句
select prod_id
from(
select prod_id,row_number() over (order by prod_id) as row_num
from products
)as subquery
where row_num between 11 and 15;
--########## End ##########
SQL查询进阶:内连接、外连接、子查询与分页优化,
575

被折叠的 条评论
为什么被折叠?



