數據庫複習—Transact-SQL語句的高級應用

6.1 多表連接
6.1.1 連接概述
  1. 連接可以根據各個表之間的邏輯關係來利用一個表中的數據選擇另外的表中的行。
  2. 連接條件可在 FROM 或 WHERE 子句中指定。連接條件與WHERE和HAVING搜索條件組合,用於控制FROM子句引用的基表中所選定的行。
  3. SQL Server處理連接時,查詢引擎從多種可能的方法中選擇最高效的方法處理連接。儘管不同連接的物理執行採用多種不同的優化,但是邏輯序列都應用下列子句實現:
  • FROM 子句中的連接條件。
  • WHERE 子句中的連接條件和搜索條件。
  • HAVING 子句中的搜索條件。
6.1.2 內連接
  1. 內連接(INNER JOIN) 通過比較數據源表間共享列的值,從多個源表檢索符合條件的行的操作。可以使用等號運算符的連接,也可以連接兩個不相等的列中的值 。

例6.1
查詢選修課程號爲c05109的學生的學號、姓名和期末成績。
select student.studentno.sname,final
from student inner join score
on student.studentno=score.studentno
where score.courseno=‘c05109’
(
use teaching
select student.studentno,sname,final
from student,score
where score.courseno=‘c05109’ and student.studentno=score.studentno
) 亦可

例6.2
查詢選修課程號爲c05103且平時成績高於80分的學生的學號、姓名、平時成績和期末成績。
select student.studentno,sname,usually,final
from student inner join score
on student.studentno=score.studentno and usually>80
where score.courseno=‘c05103’

6.1.3 外連接
  1. 外部連接(outer join)包括滿足搜索條件的連接表中的所有行,甚至包括在其他連接表中沒有匹配行的一個表中的行。
    (1)左外連接(left outer join)。包括 JOIN子句中左側表中的所有行。右表中的行與左表中的行不匹配時,將爲來自右表的所有結果集列賦以 NULL 值。
    例6.3
    利用左外連接方式查詢08級學生的學號、姓名、平時成績和期末成績。
    select student.studentno,sname,usually,final
    from student left join score
    on student.studentno=score.studentno
    where substring(student.studentno,1,2)=‘08’

    (2)右外連接(right outer join)
  • 外部連接的一種,其中包含 JOIN 子句中最右側表的所有行。
  • 如果右側表中的行與左側表中的行不匹配,則將爲結果集中來自左側表的所有列分配 NULL 值。

例6.4
利用右外連接方式查詢教師的排課情況。
select courseno,tname,teacher.teacherno,major
from teach_class right join teacher
on teach_class.teacherno=teacher.teacherno

(3)完全外連接

  • 若要通過在連接的結果中包括不匹配的行來保留不匹配信息,請使用完全外部連接。
  • SQL Server 提供了完全外部連接運算符 FULL OUTER JOIN,它將包括兩個表中的所有行,不論另一個表中是否有匹配的值。
    例6.5
    利用完全外連接方式查詢教師的排課情況。
    select courseno,tname,major,teacher.teacherno
    from teach_class full join teacher
    on teach_class.teacherno=teacher.teacherno
6.1.4 交叉連接(笛卡爾連接)

交叉連接(Cross Join )是在沒有WHERE子句的情況下,產生的表的笛卡兒積。兩個表作交叉連接時,結果集大小爲二者行數之積。該種方式在實際過程中用的很少。
例6.6
顯示student 表和score表的笛卡兒積。
select student.studentno,sname,score.*
from student cross join score

6.1.5 連接多個表
  • 使用SELECT語句進行連接的表數目沒有上限。但在一條SELECT語句中連接的表多於10個,那麼數據庫就很可能達不到最優化設計,SQL Server 2005引擎的執行計劃會變得非常繁瑣 。
  • 需要注意:對於3個以上關係表的連接查詢,一般遵循下列規則:連接n個表至少需要n-1個連接條件,以避免笛卡兒積的出現。爲了縮小結果集,採用多於n-1個連接條件或使用其他條件都是允許的。
    例6.7
    查詢08級學生的學號、姓名、課程名、期末成績及學分。
    select student.studentno,sname,cname,final,credit
    from score join student on
    student.studentno=score.studentno
    join course on
    score.courseno=course.courseno
    where
    substring(student.studentno,1,2)=‘08’

    例6.8
    查詢計算機學院的老師的教師號、姓名、上課班級號、課程名和學分。
    select teacher.teacherno,tname,class.classno,cname,credit
    from teach_class join teacher
    on teach_class.teacherno=teacher.teacherno
    join course on
    teach_class.courseno=course.courseno
    where teacher.department=‘計算機學院’
6.1.6 合併多個結果集
  1. UNION操作符可以將多個SELECT語句的返回結果組合到一個結果集中。該結果集包含聯合查詢中的所有查詢的全部行。下面列出了使用 UNION 合併兩個查詢結果集的基本規則:
  • 所有查詢中的列數和列的順序必須相同。
  • 數據類型必須兼容。
  1. 語法格式如下:
    select_statement union
    [all] select_statement

例6.9
合併結果集示例。
create table t1 (a int,b nchar(4),c nchar(4))
insert into t1 values(1,‘aaa’,‘jkl’)
insert into t1 values(2,‘bbb’,‘mno’)
insert into t1 values(2,‘ccc’,‘pqr’)
create table t2 (a nchar(4),b float)
insert into t2 values(‘kkk’,1.000)
insert inot t2 values(‘mmm’,3.000)
select a,b from t1 union
select b,a from t2

6.2 使用子查詢
6.2.1 子查詢介紹
  1. 子查詢就是一個嵌套在SELECT、INSERT、UPDATE或DELETE語句或其他子查詢中的查詢子查詢可以把一個複雜的查詢分解成一系列的邏輯步驟,利用單個語句的組合解決複雜的查詢問題。
  2. 可以使用連接替代子查詢,也可以使用子查詢替代表達式。
  3. SQL Server 2005對嵌套查詢的處理過程是從內層向外層處理,即先處理最內層的子查詢,然後把查詢的結果用於其外查詢的查詢條件,再層層向外求解,最後得出查詢結果。
  4. 使用子查詢時應該注意如下的事項:
  • 子查詢需要用括號括起來。
  • 當需要返回一個值或一個值列表時,可以利用子查詢代替一個表達式。也可以利用子查詢返回含有多個列的結果集替代表或連接操作相同的功能。
  • 子查詢不能夠檢索數據類型爲varchar(max)、nvarchar(max) 和 varbinary(max)的列
  • 子查詢中可以再包含子查詢,嵌套層數可以達到16層。
6.2.2 利用子查詢做表達式

在Transact-SQL語句中,可以把子查詢的結果當成一個普通的表達式來看待,用在其外查詢的選擇條件中。此時子查詢必須返回一個值或單個列值列表,此時的子查詢可以替換WHERE子句中包含IN關鍵字的表達式。

例6.10
查詢學號爲的學生的入學成績、所有學生的平均入學成績及該學生成績與所有學生的平均入學成績的差。
select studentno,sname,point
,(select avg(point) from student) as ‘平均成績’
,point -(select avg(point) from student) as ‘分數差值’
from student
where studentno=‘0828261367’

例6.11
獲取期末成績中含有高於93分的學生的學號、姓名、電話和Email。
select studentno,sname,phone,Email
from student
where studentno in (select studentno
from score where final>93)

例6.12
查詢選修課程的多於2門、且期末成績均在85分以上的學生的學號、姓名、電話和Email。
select studentno,sname,phone,Email
from student
where studentno in
(select studentno
from score where final>85
group by studentno having count(*)>2)

6.2.3 利用子查詢關聯數據
  1. 子查詢可以作爲動態表達式,該表達式可以隨着外層查詢的每一行的變化而變化。
  2. **創建關聯子查詢時,外部查詢有多少行,子查詢就執行多少次。 **

例6.13
查詢期末成績比該選修課程平均期末成績低的學生的學號、課程號和期末成績。
select studentno,couseno,final
from score as a
where final<(select avg(final)
from score as b
where a.courseno=b.courseno
group by courseno)

6.2.4 使用子查詢生成派生表
  1. 利用子查詢可以生成一個派生表,用於替代FROM子句中的數據源表,派生表可以定義一個別名,即子查詢的結果集可以作爲外層查詢的源表。實際上是在FROM子句中使用子查詢。

例6.14
查詢期末成績高於85分、總評成績高於90分的學生的學號、課程號和總評成績。
select tt.studentno,tt.courseno,tt.usually0.2+tt.final0.8 as ‘總評成績’
from (select * from score where final>85) as tt
where tt.final0.8+tt.usually0.2>90

6.2.5 使用子查詢修改表數據
  1. 利用子查詢修改表數據就是利用一個嵌套在INSERT、UPDATE或DELETE語句的子查詢成批的添加、更新和刪除表中的數據。

  2. INSERT 語句中的 SELECT 子查詢可用於將一個或多個其他的表或視圖的值添加到表中。使用 SELECT 子查詢可同時插入多行。
    例6.15
    創建一個表sc,將score表中學生的相關數據添加到sc表中,並要求計算總評成績。
    create table sc
    (studentno nchar(10) not null,
    courseno nchar(6) not null,
    total numeric(6,2) not null)
    go
    insert into sc(studentno,courseno,total)
    select studentno,courseno,final0.8+usually0.2
    from score
    where substring(studentno,1,2)=‘08’
    go
    select * from sc

  3. UPDATE語句中的SELECT子查詢可用於將一個或多個其他的表或視圖的值進行更新。使用 SELECT子查詢可同時更新多行數據。

  4. 在DELETE語句中利用子查詢可以刪除符合條件的數據行。實際上是通過將子查詢的結果作爲刪除條件表達式中的一部分。
    例6.16
    將sc表中含有總分低於80課程的所有學生總分增加5%。
    update sc
    set total=total*1.05
    where courseno in
    (select courseno from sc
    where total<80)
    select * from sc

6.2.6 exists和not exists子句
  1. EXISTS 是SQL語句中的運算符號,在子查詢中,如果存在一些匹配的行,結果爲TURE。
  2. 在執行過程中,一旦查找到第1個匹配的行,查詢就結束。
  3. NOT EXISTS 與 EXISTS 的工作方式類似。
    例6.17
    查詢student表中是否存在1990年12月12日以後出生的學生,如果存在,輸出學生的學號、姓名、生日和電話。
    select studentno,sname,birthday,phone
    from student
    where exists(
    select * from student
    where birthday<‘1990-12-12’)

附件:
使用到的數據庫:
https://pan.baidu.com/s/1Lmbw_qSmC04wnPUUgwSKRA
提取碼:djsz

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章