MySql數據庫多表操做

1、鏈接查詢[連表查詢、多表查詢]

當查詢結果的列來源於多張表時,須要將多張錶鏈接成一個大的數據集,再選擇合適的列返回mysql

mysql支持三種類型的鏈接查詢,分別爲:web

內鏈接查詢(inner join)

查詢的結果爲兩個表匹配到的數據sql

使用內鏈接,必須保證兩個表都會對應id的數據纔會被查詢出來。編程

                

 

格式:select 字段1,字段2... from 主表A inner join 從表B on 主表A.主鍵=從表B.外鍵網絡

例如:查詢學生的信息[ 成績、名字、班級 ]        咱們給學生表添加一個學生信息,而後使用該學生的主鍵id來連表查詢成績、名字和班級。負載均衡

insert into student (name,sex,age,class,description) values ('劉德華',1,17,406,'');

select achievement,name,class 
from student as a 
inner join achievement as b 
on a.id=b.sid
where id=101;

# 上面語句因位該學生只在學生表student中有數據,而成績表中沒有數據,因此使用內鏈接,連表查詢的結果是
Empty set (0.00 sec)

 

一樣,若是從表有數據,而主表沒有數據,則使用內鏈接查詢同樣沒法查詢到結果。ide

#例如,添加一個成績記錄,是不存在學生
insert into achievement (sid,cid,achievement) values (102,10,85);
 
select achievement,name,class 
from student as a 
inner join achievement as b 
on a.id=b.sid
where id=102;

右鏈接查詢(right join)

只要從表有數據,無論主表是否有數據,都會查詢到結果。[以從表的結果爲主 例如:a.id=b.sid,只要b表的sid存在就能夠 ;  a.id不存在沒關係  左表中不存在的數據使用null填充]性能

查詢的結果爲兩個表匹配到的數據,右表特有的數據,對於左表中不存在的數據使用null填充優化

             

 

格式:select 字段1,字段2... from 主表 right join 從表 on 主表.主鍵=從表.外鍵spa

select achievement,name,class from student as a 
right join achievement as b 
on a.id=b.sid
where b.sid=102;

 

左鏈接查詢(left join)

只要主表有數據,無論從表是否有數據都會被查詢出來。

查詢的結果爲兩個表匹配到的數據,左表特有的數據,對於右表中不存在的數據使用null填充

    

 

格式:select * from 表1 left join 表2 on 表1.列 = 表2.列

例如,使用左鏈接查詢學生表與成績表,查詢學生姓名及分數

select achievement,name,class 
from student as a 
left join achievement as b 
on a.id=b.sid;
等同於
select achievement,name,class 
from achievement as b 
right join student as a 
on a.id=b.sid;

總結:三種連表查詢,最經常使用的是 left join,而後inner join保證數據的一致性。右鏈接基本上都是使用左鏈接代替。

select 表.字段1,表.字段2,表.字段3..... 
from 主表
left join 從表1 on 主表.主鍵=從表1.外鍵 
left join 從表2 on 主表.主鍵=從表2.外鍵  
     # 這裏和從表2鏈接的on條件看實際狀況,也會出現從表1.主鍵=從表2.外鍵的狀況
left join 從表3 on 主表.主鍵=從表3.外鍵
     # 這裏能夠是(從表1或從表2).主鍵=從表2.外鍵的狀況
left join ...
多表關聯格式
多表查詢的效率,性能比單表要差。

多表查詢之後,還會帶來字段多了會引發字段覆蓋的狀況、

主表student      從表1 achievement   從表2 course

 name                 xxx                              name

上面三張表若是連表,則出現主表的name覆蓋從表2的name這種狀況。

上面兩個問題:

1. 把多表查詢語句能夠替換成單表查詢語句【須要優化的狀況】
2. 把重複的字段名,分別使用as來設置成別的名稱。
多表查詢的缺點

 練習:

select sum(b.achievement) sum   # 有時候as能夠不寫
from student as a
left join achievement as b on a.id=b.sid
where a.id=20;
查詢id爲20的學生的考試總分.
1. 先查305的學生信息
2. 再查305的學生成績
3. 再查305的學生成績對應的課程
4. 最後查305的學生成績對應的課程的老師
select a.name,b.achievement,c.course,d.name
from student as a
left join achievement as b on a.id=b.sid 
left join course as c on b.cid=c.id 
left join lecturer as d on d.id=c.lecturer_id 
where a.class=305;
查詢305班級全部學生的課程名稱、課程成績、以及對應課程的授課老師。
上面代碼的效果:
+--------+-------------+----------------+--------+
| name   | achievement | course         | name   |
+--------+-------------+----------------+--------+
| 譚季同 |       100.0 | Photoshop      | 唐老師 |
| 譚季同 |        79.0 | 負載均衡       | 杜老師 |
| 譚季同 |        78.5 | Flask項目      | 白老師 |
| 白瀚文 |        73.0 | go             | 陳老師 |
| 白瀚文 |        65.0 | webpy          | 林老師 |
| 白瀚文 |        86.0 | 數據分析       | 鄭老師 |
| 白瀚文 |        60.0 | API接口        | 宋老師 |
| 晁然   |         0.0 | Flask          | 陳老師 |
| 晁然   |        78.0 | Python網絡編程 | 江老師 |
| 晁然   |        78.0 | HTML5          | 丘老師 |
| 白素欣 |        81.0 | Django項目     | 易老師 |
| 白素欣 |        90.0 | Python         | 黃老師 |
| 白素欣 |        39.0 | Nginx          | 曹老師 |
| 莊曉敏 |        82.5 | Nginx          | 曹老師 |
| 莊曉敏 |        68.0 | Python         | 黃老師 |
| 莊曉敏 |       100.0 | API接口        | 宋老師 |
+--------+-------------+----------------+--------+
上面代碼的效果:

 

 

2、單表的連表查詢[自關聯查詢]

核心就是把一張表看作2張表來操做

# 建表:
create table area(
    id smallint not null auto_increment comment '主鍵ID',
    name char(30) not null comment '地區名稱',
    pid smallint not null default 0 comment '父級地區ID',
    primary key (id)
) engine=innodb charset=utf8;

insert into area (name,pid) values ('廣東',0),('深圳',1),('龍崗',2),('福田',2),('寶安',2);

 

格式:select 字段1,字段2...from 主表(當前表) as a  left join 從表(當前表) as b on a.主鍵=b.外鍵

# 主表當作保存深圳的表,
# 從表當作保存深圳子地區的表

select b.id,b.name
from area as a
left join area as b on a.id=b.pid
where a.name='深圳';
查找深圳地區的子地區,SQL代碼:

  

3、子查詢

 在一個 select 語句中,嵌入了另一個 select 語句, 那麼被嵌入的 select 語句稱之爲子查詢語句

格式:select 字段 from 表名 where 條件(另外一條查詢語句)

主查詢

主要查詢的對象,第一條 select 語句

主查詢和子查詢的關係

  • 子查詢是嵌入到主查詢中

  • 子查詢是輔助主查詢的,要麼充當條件,要麼充當數據源

  • 子查詢是能夠獨立存在的語句,是一條完整的 select 語句

##### 例如:查詢406班上大於平均年齡的學生

使用 子查詢:

1. 查詢406班學平生均年齡
2. 查詢大於平均年齡的學生

查詢406班級學生的平均身高
select name,age from student where age > (select avg(age) as avg from student where class=406) and class=406;
例如:查詢406班上大於平均年齡的學生

 

 

having

group by 字段 having 條件;

過濾篩選,主要做用相似於where關鍵字,用於在SQL語句中進行條件判斷,過濾結果的。

可是與where不一樣的地方在於having只能跟在group by 以後使用。

 

練習:查詢301班級裏的學生的平均成績大於班上平均成績的學生成績信息(name,平均分,班級)。

# 先求301班的平均成績
select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid 
where class=301;

# 判斷301中的每一個人平均成績大於上面的到的平均成績
select name,avg(achievement) from student as a
left join achievement as b on a.id=b.sid
where class=301 group by name having avg(achievement) > (select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid 
where class=301);
View Code
mysql> select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid 
where class=301;
+----------+
| achi     |
+----------+
| 68.96875 |
+----------+
1 row in set

mysql> select name,
achievement from student as a
left join achievement as b on a.id=b.sid 
where class=301;
+--------+-------------+
| name   | achievement |
+--------+-------------+
| 程星雲 | 63.5        |
| 程星雲 | 72          |
| 程星雲 | 40.5        |
| 婁鎮明 | 86.5        |
| 婁鎮明 | 85.5        |
| 柳宗仁 | 99          |
| 柳宗仁 | 60          |
| 曾嘉慧 | 90          |
| 王紫伊 | 73          |
| 王紫伊 | 0           |
| 王紫伊 | 55          |
| 黃威   | 98          |
| 黃威   | 79          |
| 黃威   | 62.5        |
| 莊信傑 | 60          |
| 莊信傑 | 79          |
+--------+-------------+
16 rows in set

mysql> select sum(achievement)
 from student as a
left join achievement as b on a.id=b.sid 
where class=301;
+------------------+
| sum(achievement) |
+------------------+
| 1103.5           |
+------------------+
1 row in set

mysql> select count
(achievement) from student as a
left join achievement as b on a.id=b.sid 
where class=301;
+--------------------+
| count(achievement) |
+--------------------+
|                 16 |
+--------------------+
1 row in set

mysql> select name,avg(achievement) from student as a
left join achievement as b on a.id=b.sid
where class=301 group by name having avg(achievement) > (select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid 
where class=301);
+--------+------------------+
| name   | avg(achievement) |
+--------+------------------+
| 婁鎮明 | 86               |
| 莊信傑 | 69.5             |
| 曾嘉慧 | 90               |
| 柳宗仁 | 79.5             |
| 黃威   | 79.83333         |
+--------+------------------+
5 rows in set

mysql> 
結果

 

 

select查詢語句的完整格式

select distinct 字段1,字段2....
from 表名 as 表別名
left join 從表1 on 表名.主鍵=從表1.外鍵
left join ....
where ....
group by ... having ...
order by ...
limit start,count
  • 執行順序爲:

    • from 表名[包括連表]

    • where ....

    • group by ...

    • select distinct *

    • having ...

    • order by ...

    • limit start,count

  • 實際使用中,只是語句中某些部分的組合,而不是所有

相關文章
相關標籤/搜索