Mysql - 查詢之關聯查詢


查詢這塊是重中之重, 關系到系統反應時間. 項目做到后期, 都是要做性能測試和性能優化的, 優化的時候, 數據庫這塊是一個大頭.

sql格式: select 列名/* from 表名 where 條件 group by 列 having 條件 order by 列 asc/desc;

這里牽涉到一個查詢執行順序的問題. 

單表查詢執行順序: 

select sex, count(Sex) as count from tch_teacher where id > 15 group by Sex having count > 5 order by Sex asc limit 1;

1-> from 表 : 首先拿到表tch_teacher

2-> where 條件 : 根據where后面的條件篩選一遍數據集合A

3-> group by 分組 : 對篩選出的數據A, 根據group by后面的列進行分組, 得到數據集B

4-> having 篩選 : 對數據集B進行進一步篩選, 得到數據集C

5-> select 數據 : 這里有四步

                         第一步 : 根據select后面的列名, 去數據集C中取數據. 得到數據集D

                         第二步 : 對數據集D中的數據進行去重操作(這一步是建立在 sql中有distinct 情況下), 得到數據集E

                         第三步 : 對數據集E進行排序操作, 得到數據集F

                         第四步 : 對數據集F進行截取數據操作, 得到最終的數據集(執行 limit 10 操作)

 在多表的時候, 優化器在優化的時候, 會有些區別, 有些地方, 會用到where條件, 然后才連表

 

一、連表查詢

1. 交叉連接 -- 笛卡爾乘積  cross join

select * from tch_teacher cross join tch_contact

這種連接方式, 沒見人用過.  如果tch_teacher,tch_contact表各有10條數據, 那么連接的結果, 就是 10 x 10 = 100 條數據. 

在mysql 中, cross join 后面是可以跟 on 和 where 的, 加上之后, 其實跟 inner join 是一樣的

 

2. 內連接 -- inner join 

內連接在不加on的情況下, 也是去求笛卡爾乘積. 不加on的用法並不推薦使用, 容易造成內存溢出的情況. 加on的時候, 在連表的時候, 就會對數據進行篩選, 以此來縮減有效數據范圍

select * from tch_teacher inner join tch_contact 

 

從上面的sql和圖片來看, inner join 的時候, 可以不加on, 也能得到一個結果, 而且這個結果和交叉連接的結果是一樣的. 

 這里還有另外兩種寫法:

select * from tch_teacher,tch_contact

select * from tch_teacher join tch_contact

得到的結果是一樣的. 

 

3. 外連接 -- left/right join on 

這里我特意加了一個on在上面, 因為不加on是會報錯的.

left join 稱之為左連接, 連接以左側表數據為准, 當右表沒有數據與之匹配的時候, 則會用null填補

right join 稱之為右連接, 與 left join 相反, 這個是以右表為准

先看下效果吧

select * from tch_teacher left join tch_contact on tch_teacher.Id = tch_contact.TId;

select * from tch_teacher right join tch_contact on tch_teacher.Id = tch_contact.TId;

其實這里還有一個full join , 不過mysql里面的full join, 着實有些讓人無語, 反正我沒這么用過, 略過不表了.

這里我做了一個小測試, 這里的數據, tch_contact的tid值, 我取的是0~100000之間的隨機數

select * from tch_teacher inner join tch_contact on tch_teacher.Id = tch_contact.TId ;

select * from tch_teacher LEFT join tch_contact on tch_teacher.Id = tch_contact.TId ;
tch_teacher tch_contact inner join(s) 結果 left join(s) 結果
十萬 十萬 0.499 99999 0.526 137017
十萬+5000 十萬 0.345 99999 0.565 142017
十萬-5000 十萬 0.472 94949 0.534 130124

這里面的值, 是我反復運行之后, 在一些離散值里面, 取得比較靠近中心點的值.

 

4. 自己連自己

mysql里面, 有一個比較好用的功能, 就是自己連自己. 我再tch_teacher表里面加入一列, CreateBy,  存放的是這個表的Id值

select a.*, b.Name as CreateByName from tch_teacher a
left join tch_teacher b on a.createby = b.id

能得到以下結果:

 

 二、union查詢

除了把幾個表通過內部關系拼成一個表結果, 還可以, 把多個表的查詢表結果拼成一個表結果. 所使用的方法就是union.

這里要注意的是, 列的順序. 如果害怕列的順序不一致不好排查, 可以把表結果的列名都重命名為相同的.

select Id, Sex, BId, `No`, Name, CreateDate from tch_teacher

union

select 0 as Id, Sex, BId, `No`, Name, CreateDate from tch_teacher_temp

union是會對最后的表結果進行去重操作的, 如果我不想去重, 只想快速得到拼接的結果, 可以使用 union all 來拼接. 

 

參考:

Mysql架構總覽


免責聲明!

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



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