关联是SQL语言中使用SELECT操作表的一种操作机制,用来联系两个或者多个表。SELECT是SQL中的查询语句,用于查询数据库中的数据。将SELECT与关联结合,就产生了关联查询。
假设一个班级有30名学生,每个学生都有自己的姓名、学号、班级、班主任等这些属性,可以发现,姓名学号是每个学生独有的,而班级、班主任、班主任电话等等信息是学生们共有的。现在如果要将这个班级的信息存储在数据库中,那么有两种存储方式。
① 建一张表,将数据都存在这一张表中,如下。
班级 | 班主任 | 班主任电话 | 学生姓名 | 学号 |
---|---|---|---|---|
六年一班 | 阿福 | 13131313131 | 小夫 | 1 |
六年一班 | 阿福 | 13131313131 | 大熊 | 2 |
六年一班 | 阿福 | 13131313131 | 静香 | 3 |
② 建多张表,将数据归类后存放,如下。
(1)
班级 | 班主任 | 班主任电话 |
---|---|---|
六年一班 | 阿福 | 13131313131 |
(2)
学生姓名 | 学号 | 班级 |
---|---|---|
小夫 | 1 | 六年一班 |
大熊 | 2 | 六年一班 |
静香 | 3 | 六年一班 |
为了方便说明,就不写30个学生信息了。可以发现,将数据都存放在一张表中,可以提高读表的可读性,但是开发者就会很麻烦,因为表中的前三列信息是一模一样的。如果有30条数据时,开发者就必须重复的填入相同的信息,麻烦又会出错。反观方法②,就对开发者十分友好,只有1列在重复。并且方法②的优势还在于,假设老师换手机号码了,只需要修改表(1)中的手机号,而不用像方法①中一个一个去修改。方法②如此便利,那么我们对这样的表进行查询呢?
现在我们在实际的数据库中设计两个表,为了SQL操作方便,我们将列的键都设置成英文字母。
(1)班级信息建表代码
CREATE TABLE `classinfo` (
`class` varchar(255) DEFAULT NULL,
`teacher` varchar(255) DEFAULT NULL,
`mobile` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
class | teacher | mobile |
---|---|---|
六年一班 | 阿福 | 13131313131 |
(2)学生信息建表代码
CREATE TABLE `stuinfo` (
`name` varchar(255) DEFAULT NULL,
`id` varchar(255) DEFAULT NULL,
`class` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
name | id | class |
---|---|---|
小夫 | 1 | 六年一班 |
大熊 | 2 | 六年一班 |
静香 | 3 | 六年一班 |
现在我们需要查看id为1的学生信息
SELECT classinfo.class, teacher, mobile, name, id
FROM classinfo, stuinfo
WHERE classinfo.class = stuinfo.class AND id = 1
ORDER BY id
执行结果如下
class | teacher | mobile | name | id |
---|---|---|---|---|
六年一班 | 阿福 | 13131313131 | 小夫 | 1 |
产生上面这样的结果,实际上在数据库运行中分为这三步:
(1)建立笛卡尔积
FROM classinfo, stuinfo
该语句指定了classinfo, stuinfo 这两个表关联,系统会根据这两个表生成一个笛卡尔积。按照这个笛卡尔积生成的表我认为是这样的:
class | teacher | mobile | name | id |
---|---|---|---|---|
六年一班 | 阿福 | 13131313131 | 小夫 | 1 |
六年一班 | 阿福 | 13131313131 | 大熊 | 2 |
六年一班 | 阿福 | 13131313131 | 静香 | 3 |
为了更直观的表示笛卡尔积
classinfo现在改成
class | teacher | mobile |
---|---|---|
六年一班 | 阿福 | 13131313131 |
六年二班 | 特鲁 | 12121212121 |
此时再对classinfo与stuinfo求笛卡尔积,结果如下。
class | teacher | mobile | name | id |
---|---|---|---|---|
六年一班 | 阿福 | 13131313131 | 小夫 | 1 |
六年一班 | 阿福 | 13131313131 | 大熊 | 2 |
六年一班 | 阿福 | 13131313131 | 静香 | 3 |
六年二班 | 特鲁 | 12121212121 | 小夫 | 1 |
六年二班 | 特鲁 | 12121212121 | 大熊 | 2 |
六年二班 | 特鲁 | 12121212121 | 静香 | 3 |
可以看到,做笛卡尔其实是关联两表按行相乘,同名列保留一个。
(2)过滤
WHERE classinfo.class = stuinfo.class AND id = 1
通过这条过滤语句,系统挑出classinfo.class与stuinfo.class中键值相同的并且id列中键值为1的行,过滤完毕系统生成一个对用户不可见的中间表。
class | teacher | mobile | name | id |
---|---|---|---|---|
六年一班 | 阿福 | 13131313131 | 小夫 | 1 |
(3)挑选,并返回给用户
SELECT classinfo.class, teacher, mobile, name
此时,SELECT选择如上,返回的表如下。
class | teacher | mobile | name |
---|---|---|---|
六年一班 | 阿福 | 13131313131 | 小夫 |
此时,就可以得到学号为1的学生所有信息。
假设现在有第三个表,储存着班主任的年纪,性别的信息,我们期望得到的结果如下:
class | teacher | mobile | age | gender | name | id |
---|---|---|---|---|---|---|
六年一班 | 阿福 | 13131313131 | 31 | 男 | 小夫 | 1 |
那么我们如何使用SELECT去得到这样的结果呢?
在这里,要明白多表关联的工作机制。与两个表一样,多表查询实际上是将待查询表按顺序两两组合,将两表生成的笛卡尔积与第三个表再生成笛卡尔积,最后按照过滤、选择操作将结果返回用户。
建第三个表语句如下。
CREATE TABLE `tea` (
`teacher` varchar(255) DEFAULT NULL,
`age` varchar(255) DEFAULT NULL,
`gender` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
teacher | age | gender |
---|---|---|
阿福 | 31 | 男 |
特鲁 | 35 | 男 |
白雪 | 25 | 女 |
同上,将会产生一个3X2X3的笛卡尔表,后再进行过滤,选择,返回用户。
操作语句如下。
SELECT classinfo.class, tea.teacher, mobile, age, gender, name, id
FROM classinfo, stuinfo, tea
WHERE classinfo.class = stuinfo.class
AND classinfo.teacher = tea.teacher
AND id = 1
ORDER BY id
最终结果展示如下。
关联查询与建表的方式有关,使用数据分类的方式建表,就像打一本书,首先展示的是目录,一个目录下又包括多个章节,一个章节里又包含着许多知识点。这样将数据层层包装而不是做一个巨大的表的思想,是我们需要学习的。关联查询不仅仅包含本文中提到的查询,其中还有左外连接(左连接)查询,右外联结(右连接)查询,内联结查询等查询方式,应用于实际中不同的场景。
63094048813)]
关联查询与建表的方式有关,使用数据分类的方式建表,就像打一本书,首先展示的是目录,一个目录下又包括多个章节,一个章节里又包含着许多知识点。这样将数据层层包装而不是做一个巨大的表的思想,是我们需要学习的。关联查询不仅仅包含本文中提到的查询,其中还有左外连接(左连接)查询,右外联结(右连接)查询,内联结查询等查询方式,应用于实际中不同的场景。