MySQL之多表查詢(笛卡爾積查詢、內連接、外連接(左外連接,右外連接)、union、union all )


多表查詢
測試數據
create table emp (id int,name char(10),sex char,dept_id int);
insert emp values(1,"大黃","m",1);
insert emp values(2,"老王","m",2);
insert emp values(3,"老李","w",30);

#一張表示部門表
#存在一些沒有員工的的部門

create table dept (id int,name char(10));
insert dept values(1,"市場");
insert dept values(2,"財務");
insert dept values(3,"行政");
1. 笛卡爾積查詢
# 笛卡爾積查詢,
mysql> select *from dept,emp;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市場   |    1 | 大黃   | m    |       1 |
|    2 | 財務   |    1 | 大黃   | m    |       1 |
|    3 | 行政   |    1 | 大黃   | m    |       1 |
|    1 | 市場   |    2 | 老王   | m    |       2 |
|    2 | 財務   |    2 | 老王   | m    |       2 |
|    3 | 行政   |    2 | 老王   | m    |       2 |
|    1 | 市場   |    3 | 老李   | w    |      30 |
|    2 | 財務   |    3 | 老李   | w    |      30 |
|    3 | 行政   |    3 | 老李   | w    |      30 |
+------+--------+------+--------+------+---------+
9 rows in set (0.00 sec)



# 改進版
mysql> select *from dept,emp where dept.id = dept_id;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市場   |    1 | 大黃   | m    |       1 |
|    2 | 財務   |    2 | 老王   | m    |       2 |
+------+--------+------+--------+------+---------+

總結:

  1. 笛卡爾積查詢的結果,存在很多錯誤的數據。即數據關聯關系錯誤

    解決辦法:

    select *from dept,emp where dept.id = dept_id;
    
  2. 同時笛卡爾積的結果,會產生重復的字段信息

    解決辦法:

    select 指定字段... from dept,emp where dept.id = dept_id;
    
2. 內連接

內連接查詢本質上就是笛卡爾積查詢

mysql> select *from dept join emp ;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市場   |    1 | 大黃   | m    |       1 |
|    2 | 財務   |    1 | 大黃   | m    |       1 |
|    3 | 行政   |    1 | 大黃   | m    |       1 |
|    1 | 市場   |    2 | 老王   | m    |       2 |
|    2 | 財務   |    2 | 老王   | m    |       2 |
|    3 | 行政   |    2 | 老王   | m    |       2 |
|    1 | 市場   |    3 | 老李   | w    |      30 |
|    2 | 財務   |    3 | 老李   | w    |      30 |
|    3 | 行政   |    3 | 老李   | w    |      30 |
+------+--------+------+--------+------+---------+
9 rows in set (0.00 sec)

mysql> select *from dept join emp on dept.id=emp.dept_id;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市場   |    1 | 大黃   | m    |       1 |
|    2 | 財務   |    2 | 老王   | m    |       2 |
+------+--------+------+--------+------+---------+
2 rows in set (0.00 sec)
3. 外連接:左連接

左邊的表無論是否能夠匹配 都要完整顯示,右邊即使沒有也要顯示出來

# 需求:要查詢所有員工以及所屬的部門信息
mysql> select * from emp left join dept on dept_id= dept.id;
+------+--------+------+---------+------+--------+
| id   | name   | sex  | dept_id | id   | name   |
+------+--------+------+---------+------+--------+
|    1 | 大黃   | m    |       1 |    1 | 市場   |
|    2 | 老王   | m    |       2 |    2 | 財務   |
|    3 | 老李   | w    |      30 | NULL | NULL   |
+------+--------+------+---------+------+--------+
3 rows in set (0.00 sec)

# 注意 在外連接查詢中 不能使用where關鍵字,必須使用on 專門來做表的對應關系


4. 外連接:右連接

右邊的表無論是否能夠匹配 都要完整顯示,左邊即使沒有也要顯示出來

select *from dept full join emp on dept.id = emp.dept_id; 
5. 外連接:全連接(不支持)

無論是否匹配成功,兩邊表的數據都要全顯示

##mysql 不支持
select *from dept full join emp on dept.id = emp.dept_id; 


# 可以轉化一種思路,使用左連接 + 右連接
select *from dept left join emp on dept.id=emp.dept_id
union
select *from dept right join emp on dept.id=emp.dept_id;
6. union:聯合兩個表

過濾重復,即重復的數據不顯示。同時必須保證 兩個表的列數要相同

select * from emp
union
select * from emp;


mysql> select * from emp
    -> union
    -> select * from emp;
+------+--------+------+---------+
| id   | name   | sex  | dept_id |
+------+--------+------+---------+
|    1 | 大黃   | m    |       1 |
|    2 | 老王   | m    |       2 |
|    3 | 老李   | w    |      30 |
+------+--------+------+---------+
3 rows in set (0.00 sec)
7. union all :

不過濾重復,即重復的數據可以顯示。同時必須保證 兩個表的列數要相同

select * from emp
union all
select * from emp;


mysql> select * from emp
    -> union all
    -> select * from emp;
+------+--------+------+---------+
| id   | name   | sex  | dept_id |
+------+--------+------+---------+
|    1 | 大黃   | m    |       1 |
|    2 | 老王   | m    |       2 |
|    3 | 老李   | w    |      30 |
|    1 | 大黃   | m    |       1 |
|    2 | 老王   | m    |       2 |
|    3 | 老李   | w    |      30 |
+------+--------+------+---------+
6 rows in set (0.00 sec)

總結:

內連接表示,只顯示匹配成功的記錄。一般情況下,我們通常使用內連接

外連接表示,沒有匹配成功的也要顯示

練習:

測試數據
create table stu(id int primary key auto_increment,name char(10));

create table tea(id int primary key auto_increment,name char(10));

create table tsr(id int primary key auto_increment,t_id int,s_id int,
foreign key(s_id) references stu(id),
foreign key(t_id) references tea(id));

insert into stu values(null,"張三"),(null,"李四");
insert into tea values(null,"egon"),(null,"wer");
insert into tsr values(null,1,1),(null,1,2),(null,2,2);


需求:查出egon教過的學生

使用內連接:

mysql> select  * from tea join tsr join  stu on tea.id=tsr.t_id  and tsr.s_id = stu.id  where tea.name="egon";
+----+------+----+------+------+----+--------+
| id | name | id | t_id | s_id | id | name   |
+----+------+----+------+------+----+--------+
|  1 | egon |  1 |    1 |    1 |  1 | 張三   |
|  1 | egon |  2 |    1 |    2 |  2 | 李四   |
+----+------+----+------+------+----+--------+
2 rows in set (0.00 sec)


mysql> select  stu.name from tea join tsr join  stu on tea.id=tsr.t_id  and tsr.s_id = stu.id  where tea.name="egon";
+--------+
| name   |
+--------+
| 張三   |
| 李四   |
+--------+
2 rows in set (0.00 sec)

使用子查詢:

# 先查出egon對應的id
select id from tea where name="egon";

# 在tsr表中 查詢 egon 教過學生 的id
select s_id from tsr where  t_id = (select id from tea where name="egon");

# 在學生表中查詢出對應的id
select stu.name from stu where id in (select s_id from tsr where  t_id = (select id from tea where name="egon"));



mysql> select * from tea where name="egon";
+----+------+
| id | name |
+----+------+
|  1 | egon |
+----+------+
1 row in set (0.00 sec)


mysql> select s_id from tsr where  t_id = (select id from tea where name="egon");
+------+
| s_id |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)


mysql> select stu.name from stu where id in (select s_id from tsr where  t_id = (select id from tea where name="egon"));
+--------+
| name   |
+--------+
| 張三   |
| 李四   |
+--------+
2 rows in set (0.27 sec)

通常情況下,內連接能夠查詢出來的數據,使用子查詢也能查詢出來


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM