MySql資料庫連線查詢與自關聯(七)
阿新 • • 發佈:2018-12-17
先看個問題
- 問:查詢每個學生每個科目的分數
- 分析:學生姓名來源於students表,科目名稱來源於subjects,分數來源於scores表,怎麼將3個表放到一起查詢,並將結果顯示在同一個結果集中呢?
- 答:當查詢結果來源於多張表時,需要使用連線查詢
- 關鍵:找到表間的關係,當前的關係是
- students表的id---scores表的stuid
- subjects表的id---scores表的subid
- 則上面問題的答案是:
select students.sname,subjects.stitle,scores.score from scores inner join students on scores.stuid=students.id inner join subjects on scores.subid=subjects.id;
- 結論:當需要對有關係的多張表進行查詢時,需要使用連線join
連線查詢
- 連線查詢分類如下:
- 表A inner join 表B:表A與表B匹配的行會出現在結果中
- 表A left join 表B:表A與表B匹配的行會出現在結果中,外加表A中獨有的資料,未對應的資料使用null填充
- 表A right join 表B:表A與表B匹配的行會出現在結果中,外加表B中獨有的資料,未對應的資料使用null填充
- 在查詢或條件中推薦使用“表名.列名”的語法
- 如果多個表中列名不重複可以省略“表名.”部分
- 如果表的名稱太長,可以在表名後面使用' as 簡寫名'或' 簡寫名',為表起個臨時的簡寫名稱
練習
- 查詢學生的姓名、平均分
select students.sname,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
group by students.sname;
- 查詢男生的姓名、總分
select students.sname,avg(scores.score) from scores inner join students on scores.stuid=students.id where students.gender=1 group by students.sname;
- 查詢科目的名稱、平均分
select subjects.stitle,avg(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
group by subjects.stitle;
- 查詢未刪除科目的名稱、最高分、平均分
select subjects.stitle,avg(scores.score),max(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
where subjects.isdelete=0
group by subjects.stitle;
自關聯
- 設計省資訊的表結構provinces
- id
- ptitle
- 設計市資訊的表結構citys
- id
- ctitle
- proid
- citys表的proid表示城市所屬的省,對應著provinces表的id值
- 問題:能不能將兩個表合成一張表呢?
- 思考:觀察兩張表發現,citys表比provinces表多一個列proid,其它列的型別都是一樣的
- 意義:儲存的都是地區資訊,而且每種資訊的資料量有限,沒必要增加一個新表,或者將來還要儲存區、鄉鎮資訊,都增加新表的開銷太大
- 答案:定義表areas,結構如下
- id
- atitle
- pid
- 因為省沒有所屬的省份,所以可以填寫為null
- 城市所屬的省份pid,填寫省所對應的編號id
- 這就是自關聯,表中的某一列,關聯了這個表中的另外一列,但是它們的業務邏輯含義是不一樣的,城市資訊的pid引用的是省資訊的id
- 在這個表中,結構不變,可以新增區縣、鄉鎮街道、村社群等資訊
- 建立areas表的語句如下:
create table areas(
id int primary key,
atitle varchar(20),
pid int,
foreign key(pid) references areas(id)
);
- 從sql檔案中匯入資料
source areas.sql;
- 查詢一共有多少個省
- 查詢省的名稱為“山西省”的所有城市
select city.* from areas as city
inner join areas as province on city.pid=province.id
where province.atitle='山西省';
- 查詢市的名稱為“廣州市”的所有區縣
select dis.*,dis2.* from areas as dis
inner join areas as city on city.id=dis.pid
left join areas as dis2 on dis.id=dis2.pid
where city.atitle='廣州市';