MySQL數(shù)據(jù)庫自連接實例講解
什么是自連接?
自連接可以理解為自己連接自己,在一張表上面所進行的操作;將一張表分成兩張結(jié)構(gòu)和數(shù)據(jù)完全一樣的表(簡單理解:相當(dāng)于克隆了一張跟自己長得一模一樣的表);
但是問題來了,既然是兩張一模一樣的表,數(shù)據(jù)庫怎么區(qū)分出那張表是哪張表呢?這時候最重要的一個知識點就來了,那就是給兩張表分別取個別名。
自連接語法
自連接我所知道有以下幾種語法,有遺漏的話也歡迎大家在評論區(qū)給我補充出來。
1、內(nèi)連接
1.1隱式內(nèi)連接
select 字段列表 from 表 [as] 表別名1,表 [as] 表別名2 where 條件...;
1.2.顯式內(nèi)連接
select 字段列表 from 表 [as] 表別名1 [inner] join 表 [as] 表別名2 on 條件...;
2、外連接
2.1.左外連接
select 字段列表 from 表 [as] 表別名1 left [outer] join 表 [as] 表別名2 on 條件...;
2.2.右外連接
select 字段列表 from 表 [as] 表別名1 right [outer] join 表 [as] 表別名2 on 條件...;
注:
1.語法和內(nèi)外連接的語法一樣,只不過換成了只在一張表上面操作。
2.[ ] 里面的單詞 as 代表取別名,可寫可不寫;不寫也可以取別名,用哪種都可以啦~??
案例
可以自己插入表和數(shù)據(jù)跟著做一下。
案例演示1
商品表(tb_goods):
create table tb_goods(
id int primary key auto_increment comment '主鍵ID',
goods varchar(50) not null comment '商品',
price decimal(7,2) default 0.00 comment '商品價格'
) comment '商品表';給商品表插入數(shù)據(jù):
insert into tb_goods(goods,price) values('兒童牙刷',20),
('電動牙刷',10000),
('拼多多牙刷',9.9);
insert into tb_goods(goods) values('媽媽給買的牙刷');數(shù)據(jù)展示:

需求:
查詢比 “拼多多牙刷” 的價格貴的牙刷有哪些?
思路解析(用的是隱式內(nèi)連接),語法:
select 字段列表 from 表 [as] 表別名1,表 [as] 表別名2 where 條件...;
第一步:把 tb_goods(商品表)分成兩張一模一樣的表,分別取 g1 和 g2 兩個別名,把它們連接起來;
select * from tb_goods as g1,tb_goods as g2;
查詢結(jié)果如下:它會列出每條數(shù)據(jù)的組合情況,如下,每一種牙刷都能組成四種組合。

第二步:找出 g1 表里面的 “拼多多牙刷”;
select * from tb_goods as g1,tb_goods as g2 where g1.goods = '拼多多牙刷';
查詢結(jié)果如下:

根據(jù)上面的語句查詢出來的結(jié)果可以看到, g2 表里面的 g2.price 也已經(jīng)把每個牙刷的價格查詢出來了;

第三步:此時,只需要查詢出 g2 所有牙刷的價格(g2.price)大于 g1 “拼多多牙刷”的價格(g1.price)的數(shù)據(jù)就可以了;
select * from tb_goods as g1,tb_goods as g2 where g1.goods = '拼多多牙刷' and g2.price > g1.price;
查詢結(jié)果如下:在 g2 表里面,已經(jīng)查出了大于 g1 “拼多多牙刷”的價格數(shù)據(jù)。

第四步:然后就可以把需要的數(shù)據(jù)進行查詢;
select g2.goods,g2.price from tb_goods as g1,tb_goods as g2 where g1.goods = '拼多多牙刷' and g2.price > g1.price;
查詢結(jié)果如下:得到了最終結(jié)果,比 “拼多多牙刷” 的價格貴的牙刷,完成了需求。

最后,如果要查詢的數(shù)據(jù)更清晰的話,可以給查詢的字段取別名;
select g2.goods as '商品',g2.price as '商品價格' from tb_goods as g1,tb_goods as g2 where g1.goods = '拼多多牙刷' and g2.price > g1.price;
查詢結(jié)果如下:

溫馨提醒您:取別名不加 as 也可以,只不過是我自己的個人習(xí)慣,嘿嘿~
同樣的,用顯示內(nèi)連接也可以完成該需求:
select g2.* from tb_goods as g1 inner join tb_goods as g2 on g1.goods = '拼多多牙刷' where g2.price > g1.price;
查詢結(jié)果如下:

用左外連接也可以完成該需求:
select g2.* from tb_goods as g1 left outer join tb_goods as g2 on g1.goods = '拼多多牙刷' where g2.price > g1.price;
查詢結(jié)果如下:

案例演示2
學(xué)生表(tb_student):
create table tb_student(
id int primary key auto_increment comment '主鍵ID',
student_id char(2) not null unique comment '學(xué)號',
name varchar(50) not null comment '姓名',
age tinyint unsigned not null comment '年齡',
parent_id char(2) comment '監(jiān)護人ID'
)comment '學(xué)生表';給學(xué)生表插入數(shù)據(jù):
insert into tb_student(student_id, name, age,parent_id) VALUES('01','大頭兒子',6,'03'),
('03','小頭爸爸',31,null),
('02','小灰灰',5,'04'),
('04','灰太狼',36,null);數(shù)據(jù)展示:

需求:
查詢學(xué)生姓名及學(xué)生監(jiān)護人姓名。
思路解析(用的是隱式內(nèi)連接),語法:
select 字段列表 from 表 [as] 表別名1,表 [as] 表別名2 where 條件...;
第一步:把 tb_student(學(xué)生表)分成兩張一模一樣的表,分別取 s1 和 s2 兩個別名,把它們連接起來;
select * from tb_student as s1,tb_student as s2;

第二步:看到這個需求,你可能會覺得奇怪,為什么都沒有 學(xué)生監(jiān)護人姓名 這個字段,而只有 學(xué)生監(jiān)護人ID ;

那是因為我們可以通過 學(xué)生監(jiān)護人ID(parent_id) 關(guān)聯(lián) 學(xué)生學(xué)號(student_id),找到該學(xué)生的學(xué)生監(jiān)護人(student_id)。

比如:大頭兒子的 學(xué)生監(jiān)護人ID(parent_id)是 03,此時 03 學(xué)生學(xué)號(student_id)的家長為小頭爸爸;

SQL 語句編寫:
第一步:把 tb_student(學(xué)生表)分成兩張一模一樣的表,分別取 s1 和 s2 兩個別名,把它們連接起來;
select * from tb_student as s1,tb_student as s2;
第二步:找到 s1 表的 學(xué)生監(jiān)護人ID(parent_id)和 s2 表的 學(xué)生學(xué)號(student_id),把它們用 = 關(guān)聯(lián)起來,意思就是:通過 學(xué)生監(jiān)護人ID(parent_id)找到 學(xué)生學(xué)號(student_id);
select * from tb_student as s1,tb_student as s2 where s1.parent_id = s2.student_id;
查詢結(jié)果如下:從查詢出來的結(jié)果,就可以看到對應(yīng)的 學(xué)生姓名(s1.name) 及 學(xué)生監(jiān)護人姓名(s2.name) 都已經(jīng)被找到了。

第三步:這時候就可以對學(xué)生姓名(s1.name)及學(xué)生監(jiān)護人(s2.name)這兩個數(shù)據(jù)進行查詢;
select s1.name,s2.name from tb_student as s1,tb_student as s2 where s1.parent_id = s2.student_id;
查詢結(jié)果如下:已經(jīng)實現(xiàn)該需求。

最后,如果要查詢的數(shù)據(jù)更清晰的話,可以給查詢的字段取別名;
select s1.name as '學(xué)生姓名',s2.name as '學(xué)生監(jiān)護人姓名' from tb_student as s1,tb_student as s2 where s1.parent_id = s2.student_id;
查詢結(jié)果如下:

同樣的,用顯示內(nèi)連接也可以完成該需求:
select s1.name '學(xué)生姓名',s2.name as '學(xué)生監(jiān)護人姓名' from tb_student as s1 inner join tb_student s2 on s1.parent_id = s2.student_id;
查詢結(jié)果如下:

擴展需求
在這個學(xué)生表(tb_student)里面,家長是沒有歸屬人的,也就是 parent_id 為 <null> 的情況,比如小頭爸爸和灰太狼;

此時,我又有一個需求:我希望查詢 學(xué)生姓名 及 學(xué)生的監(jiān)護人 姓名,如果學(xué)生沒有學(xué)生的監(jiān)護人, 也要查詢出來。
此時就不能使用內(nèi)連接了,內(nèi)連接只能查出它們相互交集的數(shù)據(jù);要改成左外連接;
select s1.name '學(xué)生姓名',s2.name '學(xué)生監(jiān)護人姓名' from tb_student as s1 left join tb_student as s2 on s1.parent_id = s2.student_id;
查詢結(jié)果如下:

完。。。
總結(jié)
到此這篇關(guān)于MySQL數(shù)據(jù)庫自連接實例講解的文章就介紹到這了,更多相關(guān)MySQL自連接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL系統(tǒng)變量和自定義變量的實現(xiàn)示例
本文詳細介紹了MySQL中的系統(tǒng)變量,包括如何查看和設(shè)置全局及會話變量,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-12-12
安裝配置mysql及Navicat prenium的詳細流程
這篇文章主要介紹了安裝配置mysql及Navicat Premium的詳細流程,配置方法也真的很簡單,本文給大家詳細介紹mysql Navicat Premium安裝配置相關(guān)知識感興趣的朋友,一起學(xué)習(xí)吧2021-06-06
詳解Mysql數(shù)據(jù)庫平滑擴容解決高并發(fā)和大數(shù)據(jù)量問題
本文主要介紹了Mysql數(shù)據(jù)庫平滑擴容解決高并發(fā)和大數(shù)據(jù)量問題,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05
MySQL 8.0 之索引跳躍掃描(Index Skip Scan)
這篇文章主要介紹了MySQL 8.0 之索引跳躍掃描(Index Skip Scan)的相關(guān)資料,幫助大家學(xué)習(xí)MySQL8.0的新特性,感興趣的朋友可以了解下2020-10-10
Mysql中isnull,ifnull,nullif的用法及語義詳解
MySQL中ISNULL判斷表達式是否為NULL,IFNULL替換NULL值為指定值,NULLIF在表達式相等時返回NULL,用于空值處理、條件判斷及避免錯誤,本文給大家介紹Mysql中isnull,ifnull,nullif的用法及語義,感興趣的朋友一起看看吧2025-06-06

