MySQL数据库入门(4)——自关联

文章目录

  • 1. 自关联定义
  • 2. 自关联举例
    • 2.1. 需求
    • 2.2. 设计
    • 2.3. 简化
    • 2.4. 结论
  • 3. MySQL实现
    • 3.1. 创建数据表
    • 3.2. 批量插入数据
    • 3.3. 演练

1. 自关联定义

所谓自关联是指,一个数据表中的某个字段关联了该数据表中的另外一个字段。

2. 自关联举例

下面我们通过设计一套数据表,实现一个具体需求,来通俗解释什么叫自关联。

2.1. 需求

假设现在需要设计一套数据表,使这套数据表可以通过结构化的方式存储全国的省、市、区/县的名称和层级从属关系。如:安徽省–>合肥市–>包河区;江苏省–>南京市–>江宁区等。

2.2. 设计

首先,第一反应是按照上述三个行政层级分别创建一个数据表,即省级信息数据表、市级信息数据表、区/县级数据表,对于省级信息数据表,如表1所示:

表1 省级信息数据表
id 省份
1 安徽省
2 江苏省
3 江西省

对于市级信息表,因为要体现市和省的层级关系,在市级信息数据表2中加了parent_id字段,该字段存储了表1对应省的主键,如景德镇市隶属于江西省,则其parent_id取值为江西在表1中的id值3。

表2 市级信息数据表
id parent_id
1 合肥市 1
2 安庆市 1
3 南京市 2
4 无锡市 2
5 南昌市 3
6 景德镇市 3

对于区/县级信息数据表,类似于表2设计得到了表3,即表3中字段parent_id存储了表2中对应市的主键。

表3 区/县级信息数据表
id 区/县 parent_id
1 包河区 1
2 庐阳区 1
3 宿松县 2
4 望江县 2
5 江宁区 3
6 雨花台区 3
7 崇安区 4
8 北塘区 4

2.3. 简化

上述的设计最终将产生3张数据表,实际使用时可能较为复杂,而且如果后续希望将地区信息进一步细化,如:区/县下设乡镇,乡镇下设村等,则会进一步增加数据表数量。

鉴于上述考虑,我们思考是否可以仅通过一张数据表实现所有层级数据的存储。通过观察表1、2、3我们发现,其格式都可以统一为表4所示,只是对于表1,可以将parent_id全部视为null。

表4 行政层级统一数据表
id 行政层级名称 parent_id

基于表4的设计,我们可以将表1、2、3合并为表5,即:

表5 行政区域信息统一数据表
id 行政区域名称 parent_id
1 安徽省 null
2 江苏省 null
3 江西省 null
4 合肥市 1
5 安庆市 1
6 南京市 2
7 无锡市 2
8 南昌市 3
9 景德镇市 3
10 包河区 4
11 庐阳区 4
12 宿松县 5
13 望江县 5
14 江宁区 6

2.4. 结论

如表5所示,第9条数据中,parent_id为3,即取值为江西省的id值。则表5中字段id和parent_id之间即构成了自关联

3. MySQL实现

3.1. 创建数据表

按照表5结构在数据库test(此处创建数据库过程省略,具体请见MySQL数据库入门(2)——数据库操作基础)中创建一个名为areas的数据表。

create table areas(
	id int primary key,
	title varchar(20),
	parent_id int
	);

3.2. 批量插入数据

  • 数据准备
    所需批量数据请见中国省市插入sql语句,请将所有数据复制到txt文件后,将.txt后缀更改为.sql。
  • 插入准备
    首先按照下图所示做好数据批量插入的准备。
    MySQL数据库入门(4)——自关联_第1张图片
  • 批量插入
    在mysql>后输入以下语句,从而实现数据批量插入。
source areas.sql

3.3. 演练

-- 查询数据表areas,确定所有parent_id字段为null的记录,即全国的省级行政区域。
select * from areas where parent_id is null;

MySQL数据库入门(4)——自关联_第2张图片

-- 查询数据表areas,确定安徽省的所有市级行政区域
-- 第一步:查询出安徽省的id字段值
select id from areas where title="安徽省";
-- 第二部:根据安徽省的id字段值,查询出安徽省的所有市级行政区域
select * from areas where parent_id=340000;

MySQL数据库入门(4)——自关联_第3张图片
上述案例通过两条SQL语句实现了需求,即:先通过一条SQL语句查询areas表获取了安徽省的字段id值,然后基于表5的特征,即市级行政区域的parent_id等于省级行政区域的id,从而得出结果。

下面考虑如何仅通过一条SQL语句实现相同功能,问题在于此处仅有一张数据表,如果省级行政区域和市级行政区域各有一张表,则可以通过MySQL数据库入门(3)——数据库查询操作中学习过连接查询实现,即使用类似以下的SQL语句实现。

-- 假设有两张数据表,分别为province和city,且其结构都如表5所示
select province inner join city on province.id=city.id having province.title="安徽省";

基于上述考虑,即使现在只有一个统一的数据表情况下,也可以实现上述需求,因为可以将数据表areas同时使用两次,分别作为内连接查询语句的左表和右表,即:

-- 将数据表areas分别取别名province和city
select * from areas as province inner join areas as city on city.parent_id=province.id having province.title="安徽省";

MySQL数据库入门(4)——自关联_第4张图片

你可能感兴趣的:(MySQL)