添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

当一个数据库中只有一张数据表的时候,是否有可能需要用到连接查询?设学生选课数据库中,使用SQL语句完成查询课程的先修课,列出课程名称以及它的先修课的名称。
当一张表连接自身的连接称为 自连接 。其应用场景主要是在 构建无限多级目录 。比如线上课程的多级目录,商品类别的无限分类,以及本题所探讨的先修课程的问题。
以下就以先修课程为例进行阐述(这里只考虑每门课程只有一个直接先修课程)

2.数据表的创建及数据录入

(1) 创建表专业课程表course

#创建表专业课程表course
create table course
	id int primary key auto_increment, #课程id,自增长
	name varchar(20) not null , #课程名
	parent_id int  #先修课程名

(2)插入若干课程数据

#插入记录
insert into course values(null,'C语言程序设计',0),
(null,'HTML网页设计基础',0),
(null,'数据库应用基础',1),
(null,'数据结构',1),
(null,'Java程序设计',1),
(null,'Jsp应用程序设计',5),
(null,'SSM框架技术',6),
(null,'数据库高级应用',3),
(null,'软件测试技术',5),
(null,'JavaScript程序设计',2)

(3)查询course数据表

#查询数据表
select * from course;

查询结果如下图所示:
在这里插入图片描述

从查询结果可以看出,“C语言程序设计”,“HTML网页设计基础”两门课程没有先修课。其它课程的先修课可以通过parent_id属性找到,比如“数据库应用基础”的先修课程是“C语言程序设计”,而数据库高级应用的先修课是“数据库应用基础”。
这里看明白了,就可以继续往下看哈

3.查找每门课程的直接先修课程名称

从表设计可以看出,课程的先修课名parent_id所指示的值对应用name的值,这里介绍两种方法。

方法1:使用自连接,查找直接先修课名称
将course作自连接时,连接的条件是course(c1)的parent_id和course(c2)的id值相同。由于id为1,2的课程没有先修课,为了显示出所有课程,这里需要用到left join。

select c1.id,c1.name,c1.parent_id,c2.name from course c1 left join course c2 #对同一张表使用自连接时必须要指定表的别名,以区分为不同的表对象 on c1.parent_id = c2.id

方法2:子查询用于相关计算,查找直接先修课名称
子查询相关计算的方法比较好理解,当外层查询获得一个parent_id是传递到子查询求出先修课程对应的课程名。实现代码如下:

#子查询作为相关计算
select id,name,parent_id,
       (select name from course 
         where id = c.parent_id) as parent_name
from course c; 

两种方法运行的结果相同,结果如下图
在这里插入图片描述

4.查找出指定课程的所有先修课程名称

如何找出某一门课程的所有先修课(也就是回溯到最先修课程)呢?比如“数据库高级应用”的先修课就是“数据库应用基础”—>“C语言程序设计”。
要在这一个select语句中指出所有的一对多目录层次的所有祖先。需要在select用到mysql中的用户变量。
ps: mysql中的变量也分成若干类别,这里仅介绍用户变量

4.1了解mysql中的用户变量

mysql的用户变量只作用在当前连接的当前会话中。用@标识。比如@x,表示用户变量x, 在mysql中用户变量不需要定义,直接可以使用,其赋值方式可用使用set或select查询。
比如:

#mysql定义变量本地变量
#set赋值,可以使用=,:=两种形式赋值
set @x := 10;    #定义变量var
select @x, @x*2 as double_x; #输出 10, 20
#select赋值,只能使用:=
select @y := 10, @y*2 as double_y; #输出 10, 20

自已在mysql中运行看效果哈,这里不截图了。

4.2找出指定某课程的ID为8的前修课程id

select @id,(SELECT @id := parent_id 
            FROM course 
            WHERE id = @id) AS parent_id
from (select @id := 8) tmp,course
where @id <> 0;

在这里插入图片描述
从这个查询结果可以看到,我们找出了id为8的课程的所有先修课程的id,即3,1。
看明白这个查询没?

接下来我们解析下这个查询。
第1步:分析查询的数据源:

select *
from (select @id := 8) tmp,course

定义用户变量@id,其值为8,将查询结果作为临时表tmp与course表作笛卡儿积。结果如下图所示。
在这里插入图片描述
第2步:分析parent_id列
在这里插入图片描述
有没有觉得眼熟?Bingo,这里就是一个子查询用于相关计算,不同于我们平常写的相关子查询的是,这里每读取一行记录都会更新用户变量@id。通过不断迭代@id的值,可以找出@id为8的所有课程的先修祖先。
当找到的先修课程的parent_id值为0时,后面的记录就都为0了。
如果要把每个先修课程名称都显示出来,可不可以直接在上面查询的select的列表中添加一个name列呢?
可以尝试下哦?如果不行应该怎么做?这个问题大家可以回复在评论区,答对了送你一朵大红花。
以下我介绍一种方法

4.3找出指定某课程的ID为8的前修课程的课程名称

这里只需要将上面查询的结果集作一个派生表来使用,再与course表进行连接,就可以找出所有课程名称。

select id,name
	from (
		select @id as _id, (SELECT @id := parent_id 
					FROM course 
					WHERE id = _id) AS parent_id
		from (select @id := 8 ) vars,course) as tt
	join course c on tt._id = c.id

ps: 当然也可以用子查询哦,可以自己试试
查询结果如下:
在这里插入图片描述
如果要将这些先修课拼成一个字符串。就可以这样做:

select group_concat(name order by id separator ' / ') as 先修课程
from (select id,name
	from (
		select @id as _id, (SELECT @id := parent_id 
					FROM course 
					WHERE id = _id) AS parent_id
		from (select @id := 8 ) vars,course) as tt
	join course c on tt._id = c.id
	) as t

结果如下:
在这里插入图片描述
若要求出每门课程的所有先修课。用一个select就难以实现了,实际中可以将查询逻辑封装到存储过程中实现。

Mysql无限级目录的构建与父目录查询问题当一个数据库中只有一张数据表的时候,是否有可能需要用到连接查询?设学生选课数据库中,使用SQL语句完成查询课程的先修课,列出课程名称以及它的先修课的名称。当一张表连接自身的连接称为自连接 。其应用场景主要是在构建无限多级目录。比如线上课程的多级目录,商品类别的无限分类,以及本题所探讨的先修课程的问题。以下就以先修课程为例进行阐述(这里只考虑每门课程... 分类之间的关系是怎样的? 很明显,一个分类下面可以是多个下级分类。反过来呢,一个下级分类能够属于几个上级分类呢?这个并不确定,得看具体的业务需求。如果是多个实现上会更加复杂,为了讨论层级设计,这里先限定每个分类仅有一个上级分类。 对于某个分类,需要支持的操作如下: 对单个分类的 CURD; 查询该分类的直属下级或所有下级分类;
以版面添加为例:pid值为0的数据为第一级;pid值等于id值的数据为这个id的子级 1.在repository中创建getGroupForums方法用来存储pid值相同的数据为一组 Forum[][int] getGroupForums() //二维数组 Forum[][int] groupForums; foreach (forum; this....
文章目录一、MySQL存储引擎介绍二、MySQL逻辑架构1、逻辑架构剖析2、SQL语句的执行过程三、MySQL索引1、索引的数据结构2、索引的创建与设计原则3、索引优化和查询优化四、MySQL事务1、MySQL事务基本知识2、MySQL事务日志3、MySQL锁4、MySQL多版本并发控制 一、MySQL存储引擎介绍 MySQL存储引擎介绍 二、MySQL逻辑架构 1、逻辑架构剖析 2、SQL语句的执行过程 三、MySQL索引 1、索引的数据结构 2、索引的创建与设计原则 3、索引优化和查询优化 四、MySQ
MySQL学习笔记(5)——JOIN联表查询,自连接查询,分页和排序,子查询与嵌套查询 参考:https://www.bilibili.com/video/BV1NJ411J79W?p=18 以下SQL案例均已该建表语句为基础: major专业表 :majorid专业ID,majorname专业名称,number专业人数 student学生表:id学号,name姓名,major...
+---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | datadir | /var/lib/mysql/ | +---------------+-----------------+