MySQL數(shù)據(jù)庫自連接實(shí)例講解
什么是自連接?
自連接可以理解為自己連接自己,在一張表上面所進(jìn)行的操作;將一張表分成兩張結(jié)構(gòu)和數(shù)據(jù)完全一樣的表(簡單理解:相當(dāng)于克隆了一張跟自己長得一模一樣的表);
但是問題來了,既然是兩張一模一樣的表,數(shù)據(jù)庫怎么區(qū)分出那張表是哪張表呢?這時(shí)候最重要的一個(gè)知識(shí)點(diǎn)就來了,那就是給兩張表分別取個(gè)別名。
自連接語法
自連接我所知道有以下幾種語法,有遺漏的話也歡迎大家在評(píng)論區(qū)給我補(bǔ)充出來。
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 '商品價(jià)格' ) comment '商品表';
給商品表插入數(shù)據(jù):
insert into tb_goods(goods,price) values('兒童牙刷',20), ('電動(dòng)牙刷',10000), ('拼多多牙刷',9.9); insert into tb_goods(goods) values('媽媽給買的牙刷');
數(shù)據(jù)展示:
需求:
查詢比 “拼多多牙刷” 的價(jià)格貴的牙刷有哪些?
思路解析(用的是隱式內(nèi)連接),語法:
select 字段列表 from 表 [as] 表別名1,表 [as] 表別名2 where 條件...;
第一步:把 tb_goods(商品表)分成兩張一模一樣的表,分別取 g1 和 g2 兩個(gè)別名,把它們連接起來;
select * from tb_goods as g1,tb_goods as g2;
查詢結(jié)果如下:它會(huì)列出每條數(shù)據(jù)的組合情況,如下,每一種牙刷都能組成四種組合。
第二步:找出 g1 表里面的 “拼多多牙刷”;
select * from tb_goods as g1,tb_goods as g2 where g1.goods = '拼多多牙刷';
查詢結(jié)果如下:
根據(jù)上面的語句查詢出來的結(jié)果可以看到, g2 表里面的 g2.price 也已經(jīng)把每個(gè)牙刷的價(jià)格查詢出來了;
第三步:此時(shí),只需要查詢出 g2 所有牙刷的價(jià)格(g2.price)大于 g1 “拼多多牙刷”的價(jià)格(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 “拼多多牙刷”的價(jià)格數(shù)據(jù)。
第四步:然后就可以把需要的數(shù)據(jù)進(jìn)行查詢;
select g2.goods,g2.price from tb_goods as g1,tb_goods as g2 where g1.goods = '拼多多牙刷' and g2.price > g1.price;
查詢結(jié)果如下:得到了最終結(jié)果,比 “拼多多牙刷” 的價(jià)格貴的牙刷,完成了需求。
最后,如果要查詢的數(shù)據(jù)更清晰的話,可以給查詢的字段取別名;
select g2.goods as '商品',g2.price as '商品價(jià)格' from tb_goods as g1,tb_goods as g2 where g1.goods = '拼多多牙刷' and g2.price > g1.price;
查詢結(jié)果如下:
溫馨提醒您:取別名不加 as 也可以,只不過是我自己的個(gè)人習(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é)號(hào)', name varchar(50) not null comment '姓名', age tinyint unsigned not null comment '年齡', parent_id char(2) comment '監(jiān)護(hù)人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)護(hù)人姓名。
思路解析(用的是隱式內(nèi)連接),語法:
select 字段列表 from 表 [as] 表別名1,表 [as] 表別名2 where 條件...;
第一步:把 tb_student(學(xué)生表)分成兩張一模一樣的表,分別取 s1 和 s2 兩個(gè)別名,把它們連接起來;
select * from tb_student as s1,tb_student as s2;
第二步:看到這個(gè)需求,你可能會(huì)覺得奇怪,為什么都沒有 學(xué)生監(jiān)護(hù)人姓名 這個(gè)字段,而只有 學(xué)生監(jiān)護(hù)人ID ;
那是因?yàn)槲覀兛梢酝ㄟ^ 學(xué)生監(jiān)護(hù)人ID(parent_id) 關(guān)聯(lián) 學(xué)生學(xué)號(hào)(student_id),找到該學(xué)生的學(xué)生監(jiān)護(hù)人(student_id)。
比如:大頭兒子的 學(xué)生監(jiān)護(hù)人ID(parent_id)是 03,此時(shí) 03 學(xué)生學(xué)號(hào)(student_id)的家長為小頭爸爸;
SQL 語句編寫:
第一步:把 tb_student(學(xué)生表)分成兩張一模一樣的表,分別取 s1 和 s2 兩個(gè)別名,把它們連接起來;
select * from tb_student as s1,tb_student as s2;
第二步:找到 s1 表的 學(xué)生監(jiān)護(hù)人ID(parent_id)和 s2 表的 學(xué)生學(xué)號(hào)(student_id),把它們用 = 關(guān)聯(lián)起來,意思就是:通過 學(xué)生監(jiān)護(hù)人ID(parent_id)找到 學(xué)生學(xué)號(hào)(student_id);
select * from tb_student as s1,tb_student as s2 where s1.parent_id = s2.student_id;
查詢結(jié)果如下:從查詢出來的結(jié)果,就可以看到對(duì)應(yīng)的 學(xué)生姓名(s1.name) 及 學(xué)生監(jiān)護(hù)人姓名(s2.name) 都已經(jīng)被找到了。
第三步:這時(shí)候就可以對(duì)學(xué)生姓名(s1.name)及學(xué)生監(jiān)護(hù)人(s2.name)這兩個(gè)數(shù)據(jù)進(jìn)行查詢;
select s1.name,s2.name from tb_student as s1,tb_student as s2 where s1.parent_id = s2.student_id;
查詢結(jié)果如下:已經(jīng)實(shí)現(xiàn)該需求。
最后,如果要查詢的數(shù)據(jù)更清晰的話,可以給查詢的字段取別名;
select s1.name as '學(xué)生姓名',s2.name as '學(xué)生監(jiān)護(hù)人姓名' 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)護(hù)人姓名' from tb_student as s1 inner join tb_student s2 on s1.parent_id = s2.student_id;
查詢結(jié)果如下:
擴(kuò)展需求
在這個(gè)學(xué)生表(tb_student)里面,家長是沒有歸屬人的,也就是 parent_id 為 <null> 的情況,比如小頭爸爸和灰太狼;
此時(shí),我又有一個(gè)需求:我希望查詢 學(xué)生姓名 及 學(xué)生的監(jiān)護(hù)人 姓名,如果學(xué)生沒有學(xué)生的監(jiān)護(hù)人, 也要查詢出來。
此時(shí)就不能使用內(nèi)連接了,內(nèi)連接只能查出它們相互交集的數(shù)據(jù);要改成左外連接;
select s1.name '學(xué)生姓名',s2.name '學(xué)生監(jiān)護(hù)人姓名' 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ù)庫自連接實(shí)例講解的文章就介紹到這了,更多相關(guān)MySQL自連接內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql中關(guān)于between和in的區(qū)別
這篇文章主要介紹了mysql中關(guān)于between和in的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07MySQL 獲得當(dāng)前日期時(shí)間的函數(shù)小結(jié)
MySQL 獲得當(dāng)前日期時(shí)間的函數(shù)小結(jié),需要的朋友可以參考下。2011-12-12mysql 5.7.17 安裝配置方法圖文教程(windows)
這篇文章主要為大家分享了mysql 5.7.17 安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01union和子查詢中order?by一起使用導(dǎo)致排序失效問題及解決
這篇文章主要介紹了union和子查詢中order?by一起使用導(dǎo)致排序失效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12mysql 查詢重復(fù)的數(shù)據(jù)的SQL優(yōu)化方案
這篇文章主要介紹了mysql 查詢重復(fù)的數(shù)據(jù)的SQL優(yōu)化方案,非常不錯(cuò)的方案推薦給大家。2015-02-02IDEA 鏈接Mysql數(shù)據(jù)庫并執(zhí)行查詢操作的完整代碼
這篇文章主要介紹了IDEA 鏈接Mysql數(shù)據(jù)庫并執(zhí)行查詢操作的完整代碼,代碼不難,詳細(xì)大家看完本文肯定有意向不到的收獲,感興趣的朋友跟隨小編一起看看吧2021-05-05MySQL誤刪后使用binlog恢復(fù)數(shù)據(jù)的實(shí)現(xiàn)方法
這篇文章主要介紹了MySQL誤刪后使用binlog恢復(fù)數(shù)據(jù)的實(shí)現(xiàn)方法,使用 binlog 恢復(fù)數(shù)據(jù)的預(yù)期效果是將誤刪的數(shù)據(jù)還原到誤刪之前的狀態(tài),以減少或消除數(shù)據(jù)丟失的影響,文中有相關(guān)的代碼示例和圖文介紹,需要的朋友可以參考下2024-05-05有關(guān)mysql中sql的執(zhí)行順序的小問題
在MySQL中我們可能會(huì)遇到一些關(guān)于執(zhí)行順序的問題,下面小編就來帶大家了解一下原因以及如何解決2019-05-05