前言
前面的查詢主要都是針對一個表而言的。但是,在我們項目現實中,有更多的是多個表聯合起來查詢。所以,若一個查詢同時涉及2個以上的表,那么我們就叫它為連接查詢。連接查詢是數據庫中最重要的查詢,主要包括等值連接查詢、自然連接查詢、非等值連接查詢,自身連接查詢、外連接查詢和復合條件查詢。
一。連接查詢
1.1等值與非等值查詢
連接查詢的where字句總用來連接2個表的條件稱為連接條件或者連接謂詞。格式如下:
[<表名>.] <列名> <比較運算符> [<表名>.] <列名>
其中比如運算符有:等於(=)、大於(>)、小於(<)、大於等於(>=)、小於等於(<=)、不等於(用!=或者用<>都可以)等。
連接條件我們還可以使用我們在上面一張提到過的 between....and的形式:
[<表名>] <列名> between [表名] <列名> and[表名] <列名>
使用“=”叫等值連接,其他則稱為非等值連接。
【例子1】查詢每個學生及其選修課的情況
我們在select字句中加上了表名,這樣是為了防止混淆。如果屬性名在參加連接的各表中是唯一的,則可以省略表名前綴。因為在我們的student表和course表均有sno,所以就不能省略咯。
我們也可以使用as 為表指定別名。
當然,我們這里使用表的別名的效果不太明顯,如果在多張表連接起來的時候,使用通俗易懂的表名對我們有很大的幫助。
如果在等值連接中,把目標列中重復的屬性列去掉則為自然連接。
【例子2】用自然連接重現例子1
因為sno在2個表都有,所以需要指定表名前綴,而其余的由於不沖突,所以可以不用。
1.2自連接
連接不僅可以再2個表中進行連接,而且還可以一個表自己和自己進行連接。
自連接主要是用來顯示上下級關系或者層次關系的,
【例子3】查詢每一門課的簡介先修課(也就是先修課的先修課)
因為早course表中,只有每門課的直接先修課,而沒有先修課的先修課。要得到這個信息,就必須先對一門課找到其先修課,在按照此先修課的課程號,查找它的先修課。
我們定義了2個表,first表和second表,
這里可能有點繞,需要好好琢磨琢磨這里。
自連接我在一個oracl數據自帶的一個例子,可能比較更好的理解。在Oracle中有一個表叫emp(conn scott/tirger),emp表里有一個列叫mgr,他是每個員工管理者的員工號,如果員工沒有管理者則mgr為空。(比如在公司里,員工都屬於某個經理,經理屬於老板,而老板上面沒有人了就為空。)
OK,那我們現在需要找出誰是誰的manger,什么意思呢?我現在要找比如blake和clark的老板是king。。
select m.ename || ' is ' || n.ename || ' Manger' from emp m,emp n where n.mgr=m.empno;
結果如下:
這里找出了誰是誰的manger,用的就是自連接。
1.3外連接
OK,我們現在在學生表Student中加入一條數據:
insert into student values(005,'XiaoZhang','Male',18,'IS');
然后,我們在【例子2】去查:
我們沒有找出XiaoZhang這個人。因為XiaoZhang這個人沒有選課,所以它的數據就被拋棄了。但是,我現在想要全部學生的信息,不管他有沒有選課呢?那怎么辦呢?這個時候,我們就需要使用外連接了。
外連接,分為左外連接、右外連接以及全連接
左外連接:不僅會返回連接表中滿足連接條件的所有語句,而且還會返回不滿足連接條件的連接符左邊表的其他行。(比如例子4)
右外連接:不僅會返回連接表中滿足連接條件的所有語句,而且還會返回不滿足連接條件的連接符右1邊表的其他行。
全連接:列出所有表的值。
【例子4】重現【例子1】查詢每個學生及其選修課的情況
因為用的是左外連接,所以把左邊表student的值全部顯示出來,而不用管它有沒有選課。
右外連接也是一樣,語句如下:
select student.sno,sname,ssex,sage,sdept,cno,grade
from student righ outer join sc on(student.sno=sc.sno);
全連接語法:
select student.sno,sname,ssex,sage,sdept,cno,grade
from student inner join sc on(student.sno=sc.sno);
另外一種寫法:
在oracle中,對左外連接和右外連接還有另外一種寫法:
左外連接是:左條件 = 右條件(+)
右外連接是:左條件(+) = 右條件
比如,我們現在的例子,我們只需要這樣也可以得到一樣的結果:
select student.sno,sname,ssex,sage,sdept,cno,grade from student,sc where student.sno=sc.sno(+);
結構也是一樣的哦!。
Oracle 建議你用from語句后加Outer Join語法,而不是Oracle的Join操作符(+).而且(+)是要受下面的規則限制的,但Outer Join語法則不受。
- 你不可以 在查詢塊中使用(+) 當它同時包含 join的from語句中
- (+)只是在where語句中,並且只能對應一個表或視圖的一行字段
- 如果A和B做聯接時有多個條件,那么(+)必須完善所有的匹配條件,
如果沒有 ,oracle不會警告你~只是結果自然不同的 - 不 可以在作出一個表外查詢 另張表內查詢的(+)聯接操作
- 不可以用(+)外聯接到自己 當然Self Join是可以的
- 含 (+)的Where后的注意
OR不可用
IN不可用
子查詢不可用
我們這里也在舉一個oracle數據庫自帶的例子。有2個表emp表(員工表)和dept表(部門表) 每一個員工屬於不同的部門中。
左外連接:
select d.dname,e.ename from emp e left outer join dept d on(e.deptno=d.deptno);
當然也可以這樣寫:
select d.dname,e.ename from emp e,dept d where e.deptno=d.deptno(+);
列出了所有左邊列emp的員工名字(ename)。
右外連接:
1.4復合條件連接
所謂的復合條件查詢,在where子句中可以有多個連接條件。
【例子5】查詢選修課為2號課程並且成績在90分以下的同學
select student.sno,sname,grade
from student,sc where sc.sno=student.sno --連接謂詞,需要先對表進行連接
and sc.Cno=2 and SC.Grade<=90; ---其他的限定條件
結果如下:
二。算數運算
當我們在執行查詢的時候,我們也可以再數字列使用算術表達式(+,-,*,/)。其中,乘和除的優先級要高於加減。
【例6】為了應付上面的檢查,現在需要把分數小於80分的人,加上20分。
select sname,grade+20 from student,sc where student.sno=sc.sno and grade<80;
結果如下:
三。集合查詢
本來這部分應該放到下一章節里講的,可是因為嵌套查詢的內容比較多,所以就提前講的,里面的一些嵌套內容大家先了解下。
select語句的查詢結果是元組的集合,所有多個select語句的結構可以進行集合操作。
集合操作包括並操作Union、交操作Intersect、差操作except。需要特別注意的是,參加集合操作的各查詢結果的列數必須相同;對應的數據類型也必須相同。
把這些和數學上的交集、並集以及差集就很好理解了。
3.1並操作Union
也就是or操作,把符合條件的列都列出來。
【例7】查詢計算機系的學生以及年齡不大於20歲的學生
select * from student where sdept='CS' Union select * from Student where sage<20;
等價於:
select * from student where sdept='CS' or sage<20;
結果如下:
使用Union將多個查詢結果合並起來,系統會自動去除重復元組,如果要保留重復元組則要用Union All操作符。
3.2交操作Interact
【例7】查詢計算機系的學生以及年齡不大於20歲的學生的交集
select * from student where sdept='CS' Intersect select * from Student where sage<20;
也就是等價於:
select * from student where sdept='CS' and sage<20;
結果如下:
【例8】查詢既選修課程1又選修課程2的學生。
select sno from sc where cno=1
intersect
select sno from sc where cno=2;
也就是:
select Sno from sc where cno=1 and Sno in( select Sno from sc where cno=2); ---這個表達式會在下面一章節中介紹。
3.3差集except
【例9】查詢計算機系的學生以及年齡不大於20歲的學生的差集
select * from student where sdept='CS' minus select * from student where sage<20;
要記得的是不大於。等價於下面的SQL語句:
select * from student where sdept='CS' and sage>20;
均可以得到下面的結果: