表連線,子查詢,exists
表連線的本質
資料庫連線的本質:引用。
create database xuanke;
create table stu(sid int,sname varchar(20),sphonum char(11));
create table tea(tid int,tname varchar(20),tphonum char);
create table course(cid int,cname varchar(20));
create table xuanke1(sid int,tid int,cid int,xuefen int
insert into stu values(1,'李三' ,'110');
insert into stu values(2,'王衝','120');
insert into stu values(3,'安徽','130');
insert into tea values(1113,'劉老師','1111');
insert into tea values(1114,'王老師','2222');
insert into course values(1,'linux');
insert into course values(2,'mysql');
insert into course values(3,'hadoop');
insert into xuanke1 values (1,1113,2,2);
insert into xuanke1 values(1,1114,2,4);
insert into xuanke1 values(1,1113,3,6);
insert into xuanke1 values(2,1113,2,2);
insert into xuanke1 values(2,1114,1,2);
insert into xuanke1 values(2,1113,3,2);
要求:
查詢選擇了哪些課程,課程名字,學分,老師。
select s.sname,t.tname,c.cname,x.xuefen
from stu s,tea t,course c,xuanke1 x --》設定別名
where s.sid=x.sid AND t.tid=x.tid AND c.cid=x.cid
group by ...having...
order by...
1.首先確認我們需要的資料來自於哪些表
2.看這些表中有什麼關聯關係
3.填寫select語句
主鍵、外來鍵
主鍵:
- 列
- 這個列裡面的每一個值唯一的代表著這一行資料。
- 值唯一,不能有重複,不能為空
- 例:學生表的學號列。
- 外來鍵:
- 列
- 這個列的所有資料來自於主表對應的主鍵。
- eg:選課表裡的學號列,是引用的學生表的主鍵列學生列。
表連線的多種寫法
①
select s.sname,t.tname,c.cname,x.xuefen
from stu s,tea t,course c,xuanke1 x --》設定別名
where s.sid=x.sid AND t.tid=x.tid AND c.cid=x.cid
group by ...having...
order by...
②
select s.name,t.name,c.name,x.xuefen
from stu s
join xuanke x --》表名
on s.sid=x.xid --》條件
join tea t
on x.tid=t.tid
join course c
on c.cid=x.cid
③
join xuanke x --》表名
using(sid) --》關聯列的兩列的名字必須一樣!
④
natural join xuanke x --》表名
外連線
例:將所有學生以及他們的選課資訊都列出來。
所有學生資訊、他們對應的選課資訊
左外連線
“所有”兩字落在主表上。 (主表裡有的,外表不一定有–》例如:王五,沒有選課)
select s.name,x.xuefen
from stu s
left join xuanke x
on s.sid=x.sid (會顯示空值)
右外連線
將所有的選課資訊以及對應的學生列出來
(選課的學號列一定來自學生資訊的學號列)
(假設2號學生輟學了,但他曾經選過課)
(即:選課資訊裡有的,但是學生資訊裡沒有)
right join
on
笛卡爾連線
select s.name,t.name,c.name,x.xuefen
from stu s,tea t,course c,xuanke x;
注意:要避免笛卡爾連線!!因為會產生大量無效資訊!
子查詢
無關子查詢
子查詢:select裡面還有select (- _ -)
標量子查詢(單行單列)
例1:
1.求1號球隊的隊長的編號
select name from PLAYERS where PLAYERNO=(select PLAYERNO from TEAMS where TEAMNO=1)
例2:對於編號小於60的球員,得到他們加入俱樂部的年份和104號球員加入俱樂部的年份之間的差值。
==》
select PLAYERNO,name,joined - (select joined from PLAYERS where PLAYERS=104) from PLAYERS where PLAYERSNO<60
[一個列減去一個值,返回的還是單行單列。]
例3:得到27和44號球員的生日。
select (select birth_date from players where playerno=27);
select (select birth_date from players where playerno=44);
例4:查詢生日小於聯盟隊員編號為9999的球員生日的球員的編號和姓名。
select playerno,NAME
from players
where birth_date<(
select birth_date from players where leagueno='9999');
行子查詢(多列單行)
查詢和104號球員性別相同並且住在同一城市的球員的編號。
select playerno
from players
where(sex,town)=(select sex,town from players where playerno=104)
and playerno<>104;
列子查詢(單列多行)
例:查詢至少參加了一場比賽的球員的編號和姓名。
select playerno,NAME
from players
where playerno IN(select playerno from matches);
例2:查詢那些最老的球員的編號、姓名和生日。最老的球員指的是出生日期小於等於所有其它球員的球員
SELECT playerno,NAME,birth_date
FROM players
WHERE birth_date <=ALL (
SELECT birth_date
FROM players);
PS:
<=all() 小於最小的。
any() 大於最小的。
表子查詢(多行多列)
例:得到編號小於10的男性球員的編號。
SELECT playerno
FROM ( SELECT playerno,sex
FROM players
WHERE playerno < 10 ) AS player10
WHERE sex='M';
例2:得到編號大於10 而小於100,並且加入俱樂部的年份大於1980的男性球員的編號。
第4層子查詢得到編號大於10的所有球員的編號、性別和加入時間
第3層子查詢從上面得到編號小於10 的所有球員的編號、性別和加入時間
第2層子查詢從上面得到年份大於1980所有球員的編號、性別
最外層子查詢從上面得到男性球員的編號
SELECT playerno
FROM
(SELECT playerno, sex
FROM
(SELECT playerno, sex, joined
FROM
(SELECT playerno, sex, joined
FROM players
WHERE playerno > 10) great10
WHERE playerno < 100) less100
WHERE joined > 1980) joined1980
WHERE sex = ‘M’ ;
{對子查詢來說,先執行最最裡面的子查詢。}
相關子查詢
相關子查詢:子查詢中使用到了外部查詢的表中的任何列。先執行外部查詢,然後執行子查詢。
相關子查詢的執行步驟:
1、先執行外部查詢,得到的行叫做候選行
2、使用某個候選行來執行子查詢
3、使用子查詢的返回值來決定該候選行是出現在最終的結果集中還是被丟棄
4、重複以上步驟2和3,將所有的候選行處理完畢,得到最終的結果
相關子查詢的where條件中一定有主查詢的一個列。
EXISTS和NOT EXISTS
EXISTS操作符:
該操作符專門判斷子查詢的結果集是否不為空:如果不為空則返回true,否則返回false
例:得到那些至少支付了一次罰款的球員的名字和首字母 。
SELECT NAME,initials
FROM players p
WHERE EXISTS (
SELECT 1
FROM penalties
WHERE playerno = p.playerno );
例2:得到那些不是隊長的球員的名字和首字母 。
SELECT NAME,initials
FROM players p
WHERE NOT EXISTS(
SELECT 1
FROM teams
WHERE playerno = p.playerno );