數據庫的查詢、視圖和遊標

創建數據庫和保存數據的主要目的是使用這些數據,使用的主要方法就是查詢。查詢的數據源可以來自一個或多個基本表及由此形成的數據集。

視圖是由一個或多個基本表導出的數據信息,是組織信息的邏輯表,對於管理和查詢數據非常方便。

遊標在數據庫與應用程序之間提供了數據處理單位的變換機制。

本章介紹數據庫的查詢、視圖和遊標。

4.1 數據庫的查詢:SELECT

說明從這個主體語法可以看出,SELECT語句返回一個表的結果集,通常該結果集稱爲表值表達式。

4.1.1 選擇查詢結果輸出列:* /列表下面分不同情況說明選擇查詢結果輸出列。

1. 選擇所有列

【例4.1】查詢xscj數據庫中xsb表的所有數據。

SELECT *  FROM xsb

2. 選擇一個表中指定的列

SELECT 學號,姓名,總學分
	FROM xsb
	WHERE 專業 = '計算機'

3. 定義列別名

當希望查詢結果中的某些列或所有列顯示時使用自己定義的列標題時,可以在列名之後使用AS子句來更改查詢結果的列標題名。

【例4.3】查詢xsb表中計算機系同學的學號、姓名和總學分,結果中各列的標題分別指定爲number、name和mark。代碼如下,執行結果如圖4.2所示。

SELECT 學號 AS number,姓名 AS name,總學分 AS mark
	FROM xsb
	WHERE 專業 = '計算機'

更改查詢結果中的列標題也可以使用“列別名=表達式”的形式。例如:

SELECT number = 學號,name = 姓名 ,mark = 總學分
	FROM xsb
	WHERE 專業 = '計算機'

當自定義的列標題中含有空格時,必須使用引號將標題括起來。例如:

SELECT 'Student number' = 學號,姓名 AS 'Student name' ,mark = 總學分, 性別
	FROM xsb
	WHERE 專業 = '計算機'

說明不允許在WHERE子句中使用列別名。這是因爲,執行WHERE代碼時,可能尚未確定列值。例如,下述查詢是非法的:

SELECT 性別 AS SEX FROM xsb WHERE SEX = 0

插入成績表數據cjb

INSERT INTO cjb
VALUES
('191301','102',78),
('191301','206',76),
('191303','101',62),
('191303','102',70),
('191303','206',81),
('191304','101',90),
('191304','102',84),
('191304','206',65),
('191302','102',78),
('191302','206',78),
('191306','101',65),
('191306','102',71),
('191306','206',80),
('191307','101',78),
('191307','102',80),
('191307','206',68),
('191308','101',85),
('191308','102',64),
('191308','206',87),
('191309','101',66),
('191309','102',83),
('191309','206',70),
('191310','101',95),
('191310','102',90),
('191310','206',89),
('191311','101',91),
('191311','102',70),
('191311','206',76),
('191313','101',63),
('191313','102',79),
('191313','206',60),
('221301','101',80),
('221302','101',65),
('221303','101',87),
('221304','101',91),
('221310','101',76),
('221316','101',81),
('221318','101',70),
('221320','101',82),
('221321','101',76),
('221341','101',90)

4. 替換查詢結果中的數據

在對錶進行查詢時,有時希望對所查詢的某些列得到的是一種概念而不是具體的數據。例如,查詢xsb表的總學分,希望知道的是學習的總體情況,這時,就可以用等級來替換總學分的具體數字。

要替換查詢結果中的數據,則要使用查詢中的CASE表達式,格式爲:

【例4.4】查詢xsb表中計算機系各同學的學號、姓名和總學分,對其總學分按以下規則進行替換:若總學分爲空值,則替換爲“尚未選課”;若總學分小於50,則替換爲“不及格”;若總學分在50與52之間,則替換爲“合格”;若總學分大於52,則替換爲“優秀”。列標題更改爲“等級”。

SELECT 學號,姓名,等級=
	CASE 
		WHEN 總學分 IS NULL THEN '尚未選課'
		WHEN 總學分 < 50 THEN '不及格'
		WHEN 總學分 >=50 and 總學分<=52  THEN '合格'
		ELSE '優秀'
	END
FROM xsb
WHERE 專業='計算機'

 

5. 計算列值

使用SELECT對列進行查詢時,在結果中可以輸出對列值計算後的值,即SELECT子句可使用表達式作爲結果,格式爲:

【例4.5】按120分計算成績並顯示學號爲“191301”的學生的成績情況。

代碼如下,執行結果如圖4.4所示。

SELECT 學號,課程號,成績120=成績*1.20
	FROM cjb
	WHERE 學號='191301'

計算列值使用算術運算符:+(加)、−(減)、*(乘)、/(除)和%(取餘)。其中,算術運算符(+、−、*、/)可以用於任何數字類型的列,包括int、smallint、tinyint、decimal、numeric、float、real、money和smallmoney;%可以用於上述除money和smallmoney以外的數字類型。

6. 消除結果集中的重複行

對錶只選擇某些列時,可能會出現重複行。例如,若對xscj數據庫的xsb表只選擇專業和總學分,則出現多行重複的情況。可以使用DISTINCT關鍵字消除結果集中的重複行,其格式是:

關鍵字DISTINCT的含義是:對結果集中的重複行只選擇一個,保證行的唯一性。

【例4.6】對xscj數據庫的xsb表只選擇專業和總學分,消除結果集中的重複行。

SELECT DISTINCT 專業,總學分 FROM xsb

與DISTINCT相反,當使用關鍵字ALL時,將保留結果集中的所有行。當SELECT語句中省略ALL與DISTINCT時,默認值爲ALL。

7. 限制結果集返回行數

如果SELECT語句返回的結果集的行數非常多,那麼可以使用TOP選項限制其返回的行數。TOP選項的基本格式爲:

指示只能從查詢結果集返回指定的第一組行或指定的百分比數目的行。“表達式”可以是指定數目或百分比數目的行。若帶PERCENT關鍵字,則表示返回結果集的前(表達式值)%行。

【例4.7】對xscj數據庫的xsb表選擇姓名、專業和總學分,返回結果集的前6行。

SELECT TOP 6 姓名, 專業,總學分 FROM xsb

8. 選擇用戶定義數據類型列

有關用戶定義數據類型的內容將在後面章節詳細討論。

9. 聚合函數

SELECT子句的表達式中還可以包含所謂的聚合函數。聚合函數常常用於對一組值進行計算,然後返回單個值。聚合函數通常與GROUP BY子句一起使用。如果一個SELECT語句中有一個GROUP BY子句,則這個聚合函數對所有列起作用;如果沒有,則SELECT語句只產生一行作爲結果。SQL Server所提供的聚合函數如表4.1所示。

下面對常用的聚合函數進行介紹。

(1)SUM和AVG

SUM和AVG分別用於求表達式中所有值項的總和與平均值,語法格式爲:

其中,“表達式”可以是常量、列、函數或表達式,其數據類型只能是int、smallint、tinyint、bigint、decimal、numeric、float、real、money和smallmoney。ALL表示對所有值進行運算,DISTINCT表示去除重複值,默認爲ALL。SUM / AVG忽略NULL值。

SELECT SUM(學分)  AS '總學分'  FROM kcb

執行結果如圖4.6所示。

使用聚合函數作爲SELECT的選擇列時,若不爲其指定列標題,則系統將對該列輸出標題“無列名”。

SELECT AVG(成績) AS '選修101課程學生平均成績' 
FROM cjb WHERE 課程號=101

(2)MAX和MIN

MAX和MIN分別用於求表達式中所有值項的最大值與最小值,語法格式爲:

其中,“表達式”可以是常量、列、函數或表達式,其數據類型可以是數字、字符和時間日期類型。ALL、DISTINCT的含義及默認值與SUM/AVG函數相同。MAX/MIN忽略NULL值。

【例4.9】求選修101課程的學生的最高分和最低分。

SELECT MAX(成績) AS '計處機基礎最高分',MIN(成績) AS '計算機基礎最低分'
FROM cjb
WHERE 課程號= '101'

(3)COUNT

COUNT用於統計組中滿足條件的行數或總行數,格式爲:

其中,“表達式”的數據類型是除text、image或ntext之外的任何類型。ALL、DISTINCT的含義及默認值與SUM/AVG函數相同,COUNT忽略NULL值。

【例4.10】求學生的總數、總學分在50分以上的人數和專業個數。

SELECT  COUNT(*) AS '學生總數',COUNT (DISTINCT 專業) AS '專業個數'
FROM xsb;
GO
SELECT  COUNT(總學分) AS '總學分>50人數'
FROM xsb
WHERE 總學分>50
GO

查詢結果如下:

使用COUNT(*)時將返回檢索行的總數目,不論其是否包含NULL值。COUNT_BIG函數的格式、功能與COUNT函數相同,區別僅在於COUNT_BIG返回bigint類型值。

4.1.2 選擇查詢條件:WHERE

下面分不同情況說明選擇查詢條件。

1. 表達式比較

比較運算符用於比較兩個表達式值,共有9個,分別是=(等於)、<(小於)、<=(小於等於)、>(大於)、>=(大於等於)、<>(不等於)、!=(不等於)、!<(不小於)、!>(不大於)。比較運算的格式爲:

其中,“表達式”是除text、ntext和image以外類型的表達式。

當兩個表達式值均不爲空值(NULL)時,比較運算返回邏輯值TRUE(真)或FALSE(假)。而當兩個表達式值中有一個爲空值或都爲空值時,比較運算將返回UNKNOWN。

可以將多個判定運算的結果通過邏輯運算符(NOT、AND和OR)再組成更爲複雜的查詢條件。

【例4.11】查詢xsb表中通信工程專業總學分大於等於42的同學的情況。

SELECT * 
	FROM xsb
	WHERE 專業= '通信工程' AND 總學分 >=42

2. 模式匹配

LIKE謂詞用於指出字符串是否與指定的字符串相匹配,返回邏輯值TRUE或FALSE。LIKE謂詞表達式的格式爲:

說明(1)表達式:一般爲字符串表達式,在查詢語句中可以是列名。

(2)模式串:可以使用通配符,表4.2列出了LIKE謂詞可以使用的通配符及其說明。

(3)轉義符:應爲有效的SQL Server字符,沒有默認值,且必須爲單個字符。當模式串中含有與通配符相同的字符時,應通過該字符前的轉義符指明其爲模式串中的一個匹配字符。使用ESCAPE可指定轉義符。

(4)NOT  LIKE:NOT LIKE與LIKE的作用相反。

使用帶%通配符的LIKE時,模式字符串中的所有字符都有意義,包括起始或尾隨空格。

【例4.12】查詢xsb表中姓“王”且單名的學生情況。

SELECT *
FROM xsb
WHERE 姓名 LIKE '王_'

【例4.13】查詢xsb表中學號倒數第5個數字爲9,最後1個數在1~5的學生學號、姓名及專業。

SELECT 學號,姓名,專業
FROM xsb
WHERE 學號 LIKE '%9___[1-5]'

如果需要查找一個通配符,則必須使用一個轉義字符。

3. 範圍比較

用於範圍比較的關鍵字有兩個:BETWEEN和IN。

(1)當要查詢的條件是某個值的範圍時,可以使用BETWEEN關鍵字。BETWEEN關鍵字指出查詢範圍,格式爲:

當不使用NOT時,若“表達式”的值在“表達式1”與“表達式2”之間(包括這兩個值),則返回TRUE,否則返回FALSE;當使用NOT時,返回值剛好相反。

注意“表達式1”的值不能大於“表達式2”的值。

【例4.14】查詢xsb表中不在1995年出生的學生情況。

SELECT 學號,姓名,專業,出生時間
FROM xsb
WHERE 出生時間 NOT BETWEEN '1995-1-1' and '1995-12-31'

(2)使用IN關鍵字可以指定一個值表,值表中列出所有可能的值,當與值表中的任何一個匹配時,即返回TRUE,否則返回FALSE。使用IN關鍵字指定值表的格式爲:

【例4.15】查詢xsb表中專業爲“軟件工程”或“通信工程”學生的情況。

SELECT  *
FROM  xsb
WHERE 專業 IN ('軟件工程','通信工程')

也下面查詢語句相同:

SELECT  *
FROM  xsb
WHERE 專業 ='軟件工程' OR 專業='通信工程'

4. 空值比較

當需要判定一個表達式的值是否爲空值時,使用IS NULL關鍵字,格式爲:

當不使用NOT時,若表達式的值爲空值,則返回TRUE,否則返回FALSE;當使用NOT時,結果剛好相反。

【例4.16】查詢備註爲空(沒有備註內容)的學生。

SELECT *
FROM xsb
WHERE 備註 IS NULL

5. 子查詢

在查詢條件中,可以使用另一個查詢的結果作爲條件的一部分,例如,判定列值是否與某個查詢的結果集中的值相等,作爲查詢條件一部分的查詢稱爲子查詢。

T-SQL允許SELECT多層嵌套使用,用來表示複雜的查詢。子查詢除了可以用在SELECT語句中,還可以用在INSERT、UPDATE及DELETE語句中。子查詢通常與IN、EXIST謂詞及比較運算符結合使用。

(1)IN子查詢

IN子查詢用於判斷一個給定值是否在子查詢結果集中,格式爲:

當表達式與子查詢的結果表中的某個值相等時,IN謂詞返回TRUE,否則返回FALSE;若使用了NOT,則返回的值剛好相反。

【例4.17】查找選修了課程號爲206的學生的情況。

在“查詢分析器”窗口中輸入並執行如下查詢腳本:

SELECT * 
	FROM xsb
	WHERE 學號 IN 
	(SELECT 學號
		FROM cjb
		WHERE 課程號='206'
	)

本例中,先執行子查詢:

得到一個只含有學號列的表,cjb表中每個課程名列值爲206的行在結果表中都有一行。再執行外查詢,若xsb表中某行的學號列值等於子查詢結果表中的任一個值,該行就被選擇。

IN和NOT IN子查詢只能返回一列數據。對於較複雜的查詢,可以使用嵌套的子查詢。

例4.18】查找未選修離散數學的學生情況。

SELECT * 
	FROM xsb
	WHERE 學號 NOT IN
	(
		SELECT 學號
			FROM cjb
			WHERE 課程號 IN
			(
				SELECT 課程號
				FROM kcb
				WHERE 課程名 = '離散數學' 
			)
	)

(2)比較子查詢

這種子查詢可以認爲是IN子查詢的擴展,它使表達式的值與子查詢的結果進行比較運算,格式爲:

 

其中,ALL、SOME和ANY說明對比較運算的限制。

ALL指定表達式要與子查詢結果集中的每個值都進行比較,當表達式與每個值都滿足比較的關係時,才返回TRUE,否則返回FALSE。

SOME或ANY表示表達式只要與子查詢結果集中的某個值滿足比較的關係,就返回TRUE,否則返回FALSE。

【例4.19】查找選修了離散數學的學生學號。

SELECT 學號
	FROM cjb
	WHERE 課程號 = 
	(
		SELECT 課程號
			FROM kcb
			WHERE 課程名= '離散數學'
	)

【例4.20】查找比所有計算機系的學生年齡都大的學生。

SELECT *
	FROM xsb
	WHERE 出生時間 < ALL
	(
		SELECT 出生時間
		FROM xsb
		WHERE 專業 = '計算機'
	)

【例4.21】查找206號課程成績不低於101號課程最低成績的學生學號。

SELECT 學號
 FROM cjb
 WHERE 課程號 = '206' AND 成績 !< ANY
 (
	SELECT 成績
	 FROM cjb
	 WHERE 課程號 ='101'
 )

【例4.22】查找選修206號課程的學生姓名。

SELECT 姓名
	FROM  xsb
	WHERE EXISTS
	(
		SELECT * 
		FROM cjb
		WHERE 學號 = xsb.學號 AND 課程號 = '206'
	)

分析:

① 子查詢的條件中使用了限定形式的列名引用“xsb.學號”,表示這裏的“學號”列出自表xsb。

② 與前面的子查詢例子的不同點是,前面的例子中內層查詢只處理一次,得到一個結果集,再依次處理外層查詢;而本例的內層查詢要處理多次,因爲內層查詢與xsb.學號有關,外層查詢中xsb表的不同行有不同的學號值。這類子查詢稱爲相關子查詢,因爲子查詢的條件依賴於外層查詢中的某些值。

其處理過程如下:

首先查找外層查詢中xsb表的第一行,根據該行的學號列值處理內層查詢,若結果不爲空,則WHERE條件爲真,就把該行的姓名值取出作爲結果集的一行;然後再找xsb表的第2、第3、…、第n行,重複上述處理過程直到xsb表的所有行都查找完爲止。

【例4.23】查找選修了全部課程的同學的姓名。

SELECT 姓名
FROM xsb
WHERE NOT EXISTS
(
	SELECT * 
		FROM kcb
		WHERE NOT EXISTS
		(
			SELECT * 
			FROM cjb
			WHERE 學號 = xsb.學號 AND 課程號 = kcb.課程號
	)
)

說明由於沒有人選全部課程,所以結果爲空。

另外,子查詢還可以用在SELECT語句的其他子句中,如FROM子句。SELECT關鍵字後面也可以定義子查詢。

【例4.24】從xsb表中查找所有女學生的姓名、學號及其與“191301”號學生的年齡差距。

SELECT  學號,姓名,YEAR(出生時間) - 
		YEAR(( SELECT 出生時間
				FROM xsb
				WHERE 學號='191301'
				)
			)
FROM xsb
WHERE 性別 = 0

說明YEAR函數用於取出日期類型數據的年份。

4.1.3 指定查詢對象:FROM

SELECT的查詢對象由FROM子句指定,查詢對象主要包括表或視圖,稱爲表源。

1. 表或視圖名

表或視圖名指定SELECT語句要查詢的表或視圖,表和視圖可以是一個或多個,有關視圖的內容在下一節中介紹。

【例4.25】查找kcb表中101號課程的開課學期。

USE sxcj
GO
SELECT 開課學期
	FROM kcb
	WHERE 課程號 = '101'

查詢結果爲1。

【例4.26】查找191301號學生計算機基礎課的成績。

SELECT 成績
	FROM cjb,kcb
	WHERE cjb.課程號=kcb.課程號 AND 學號='191301' 

可以使用AS選項爲表指定別名,AS關鍵字也可以省略,直接給出別名即可。別名主要用在相關子查詢及連接查詢中。如果FROM子句指定了表別名,則這條SELECT語句中的其他子句都必須使用表別名來代替原始的表名。

【例4.27】查找選修了與學號爲191302的同學所選修的課程完全相同的同學的學號。


--查找選修了與學號爲191302的同學所選修的課程完全相同的同學的學號。
SELECT DISTINCT
	學號 
FROM
	cjb AS CJ1 
WHERE
	NOT EXISTS (   --結果集爲空返回True,有結果集返回False
	SELECT
		* 
	FROM
		cjb AS CJ2 
	WHERE
		CJ2.學號 = '191302' 
	AND NOT EXISTS ( SELECT * FROM cjb AS CJ3 WHERE CJ3.學號 = CJ1.學號 AND CJ3.課程號 = CJ2.課程號 ) 
	)

/*
主查詢 第1行 191301 第二查詢第1行 102 AND NOT EXISTS (SELECT * FROM cjb AS CJ3 WHERE CJ3.學號 = 191301 AND CJ3.課程號 =102) False  主查詢條件爲True
主查詢 第1行 191301 第二查詢第2行 206 AND NOT EXISTS (SELECT * FROM cjb AS CJ3 WHERE CJ3.學號 = 191301 AND CJ3.課程號 =206) False  主查詢條件爲True
.
.
.
主查詢 第12行 221301 第二查詢第一行 102 AND NOT EXISTS	(SELECT * FROM cjb AS CJ3 WHERE CJ3.學號 = 221301 AND CJ3.課程號 =102) True		主查詢條件爲False
主查詢 第12行 221301 第二查詢第一行 102 AND NOT EXISTS	(SELECT * FROM cjb AS CJ3 WHERE CJ3.學號 = 221301 AND CJ3.課程號 =206)	True	主查詢條件爲False
.
.
.
*/

2. 導出表

導出表表示由子查詢中SELECT語句的執行而返回的表,但必須使用AS關鍵字爲子查詢產生的中間表定義一個別名。

【例4.28】從xsb表中查找總學分大於50的男同學的姓名和學號。

SELECT 姓名,學號,總學分
FROM ( SELECT 姓名,學號,性別,總學分
		FROM xsb
		WHERE 總學分 >=50
	)	AS student
WHERE 性別=1

說明在這個例子中,首先處理FROM子句中的子查詢,將結果放到一箇中間表中併爲表定義一個名稱student,然後再根據外部查詢條件從student表中查詢出數據。另外,子查詢還可以嵌套使用。

子查詢用於FROM子句時,也可以爲列指定別名。

【例4.29】在xsb表中查找1995年1月1日以前出生的學生的姓名和專業。

SELECT student.name,student.speciality
	FROM	(SELECT * FROM xsb WHERE 出生時間<'19950101')
	AS student (num,name,sex,birthday,speciality,score,mem)

注意若要爲列指定別名,則必須爲所有列指定別名。

4.1.4 連接:=/JOIN

連接是兩元運算,可以對兩個或多個表進行查詢,結果通常是含有參加連接運算的兩個表(或多個表)的指定列的表。例如,在xscj數據庫中要查找選修了離散數學課程的學生的姓名和成績,就需要將xsb、kcb和cjb 3個表進行連接,才能查找到結果。

在實際的應用中,多數情況下,用戶查詢的列都來自多個表。例如,在學生成績數據庫中查詢選修了某個課程號的課程的學生姓名、該課課程名和成績,所需要的列來自xsb、kcb和cjb3個表。把涉及多個表的查詢稱爲連接查詢。

在T-SQL中,連接查詢有兩類表示形式:一是符合SQL標準的連接謂詞表示形式;另一是T-SQL擴展的使用關鍵字JOIN的表示形式。

1. 連接謂詞

可以在SELECT語句的WHERE子句中使用比較運算符給出連接條件對錶進行連接,這種表示形式稱爲連接謂詞表示形式。

【例4.30】查找xscj數據庫每個學生的情況以及選修的課程情況。

SELECT xsb.*, cjb.*
	FROM xsb,cjb
	WHERE xsb.學號 = cjb.學號

結果表將包含xsb表和cjb表的所有列。

注意連接謂詞中的兩個列(即字段)稱爲連接字段,它們必須是可比的。如本例連接謂詞中的兩個字段分別是xsb和cjb表中的學號字段。不同表中的字段名,需要在字段名之前加上表名以示區別。

連接謂詞中的比較符可以是<、<=、=、>、>=、!=、<>、!<和 !>,當比較符爲“=”時,就是等值連接。

(1)自然連接

它在目標列中去除相同的字段名。

【例4.31】自然連接查詢。


SELECT xsb.*, cjb.課程號,cjb.成績
	FROM xsb,cjb
	WHERE xsb.學號 = cjb.學號

本例所得的結果表包含以下字段:學號、姓名、性別、出生時間、專業、總學分、備註、課程號、成績。若選擇的字段名在各個表中是唯一的,則可以省略字段名前的表名。

如本例的SELECT語句也可寫爲:

SELECT xsb.*, 課程號,成績
	FROM xsb,cjb
	WHERE xsb.學號 = cjb.學號

【例4.32】查找選修了206號課程且成績在80分以上的學生姓名及成績。


SELECT 姓名,成績
	FROM xsb,cjb
	WHERE xsb.學號 = cjb.學號 AND 課程號 ='206' AND 成績 >= 80

(2)多表連接

有時用戶所需要的字段來自兩個以上的表,那麼就要對兩個以上的表進行連接,稱之爲多表連接。

例4.33】查找選修了“計算機基礎”課程且成績在80分以上的學生學號、姓名、課程名及成績。

SELECT xsb.學號,姓名, 課程名,成績
	FROM xsb,kcb,cjb
	WHERE xsb.學號 = cjb.學號
		AND kcb.課程號=cjb.課程號
		AND 課程名='計算機基礎'
		AND  成績 >=80

連接和子查詢可能都要涉及兩個或多個表,要注意連接與子查詢的區別:連接可以合併兩個或多個表中的數據,而帶子查詢的SELECT語句的結果只能來自一個表,子查詢的結果是用來作爲選擇結果數據時進行參照的。

2. 以JOIN關鍵字指定的連接

T-SQL擴展了以JOIN關鍵字指定連接的表示方式,使表的連接運算能力有所增強。FROM子句的<連接表>表示將多個表連接起來。

以JOIN關鍵字指定的連接有3種類型:內連接、外連接、交叉連接。

① 內連接。

指定了INNER關鍵字的連接是內連接,內連接按照ON所指定的連接條件合併兩個表,返回滿足條件的行。

【例4.34】查找xscj數據庫中每個學生的情況以及選修的課程情況。

SELECT *
	FROM xsb  INNER  JOIN cjb
		ON xsb.學號 = cjb.學號

執行的結果將包含xsb表和cjb表的所有字段(不去除重複字段——學號)。

 

內連接是系統默認的,可以省略INNER關鍵字。使用內連接後仍可使用WHERE子句指定條件。

【例4.35】查詢選修了206課程且成績大於80的學生姓名和成績

SELECT 姓名,成績
	FROM xsb  INNER  JOIN cjb
		ON xsb.學號 = cjb.學號
	WHERE 課程號 = '206' AND 成績 >=80

內連接還可以用於多個表的連接。

【例4.36】用FROM子句的JOIN關鍵字表達下列查詢:查找選修了“計算機基礎”課程且成績在80分以上的學生學號、姓名、課程名及成績。

SELECT xsb.學號,姓名,課程名,成績
	FROM xsb  JOIN cjb JOIN kcb
		ON cjb.課程號 = kcb.課程號
		ON xsb.學號 = cjb.學號
	WHERE 課程名 = '計算機基礎' AND 成績 >=80

作爲一種特例,可以將一個表與它自身進行連接,稱爲自連接。若要在一個表中查找具有相同列值的行,則可以使用自連接。使用自連接時需爲表指定兩個別名,且對所有列的引用均要用別名限定。

【例4.37】查找不同課程成績相同的學生的學號、課程號和成績。

SELECT  a.學號,b.課程號,b.課程號,a.成績
	FROM cjb a JOIN cjb b 
	ON a.成績=b.成績 AND a.學號= b.學號 AND a.課程號!=b.課程號

② 外連接。

指定了OUTER關鍵字的連接爲外連接,外連接的結果表不但包含滿足連接條件的行,還包括相應表中的所有行。外連接包括以下3種。

• 左外連接(LEFT OUTER JOIN):結果表中除了包括滿足連接條件的行,還包括左表的所有行。

• 右外連接(RIGHT OUTER JOIN):結果表中除了包括滿足連接條件的行,還包括右表的所有行。

• 完全外連接(FULL OUTER JOIN):結果表中除了包括滿足連接條件的行,還包括兩個表的所有行。

其中的OUTER關鍵字均可省略。

【例4.38】查找所有學生情況,以及他們選修的課程號,若學生未選修任何課,也要包括其情況。

SELECT * FROM xsb
SELECT * FROM cjb
SELECT xsb.* ,課程號
	FROM xsb LEFT OUTER JOIN cjb
	ON xsb.學號=cjb.學號

本例執行時,若有學生未選任何課程,則結果表中相應行的課程號字段值爲NULL。

【例4.39】查找被選修了的課程的情況和所有開設的課程名。


SELECT cjb.*,課程名
FROM cjb RIGHT JOIN kcb
ON cjb.課程號=kcb.課程號

本例執行時,若某課程未被選修,則結果表中相應行的學號、課程號和成績字段值均爲NULL。

 

③ 交叉連接。

交叉連接實際上是將兩個表進行笛卡兒積運算,結果表是由第一個表的每一行與第二個表的每一行拼接後形成的表,因此結果表的行數等於兩個表的行數之積。

例4.40】列出學生所有可能的選課情況。

SELECT 學號,姓名,課程號,課程名
FROM xsb CROSS JOIN kcb

交叉連接也可以使用WHERE子句進行條件限定。

 

4.1.5 指定查詢結果分組方法:GROUP BY

GROUP BY子句主要用於根據字段對行分組。例如,根據學生所學的專業對xsb表中的所有行分組,結果是每個專業的學生成爲一組。GROUP BY子句有ISO標準和非ISO標準兩種語法格式可用。這裏介紹ISO標準的GROUP BY子句。

語法格式如下:

【例4.41】在xscj數據庫上產生一個結果集,包括每個專業的男生、女生人數,總人數及學生總人數。

代碼如下,執行結果如圖4.16所示。

SELECT 專業,性別,COUNT(*) AS '人數'
FROM xsb
GROUP BY ROLLUP(專業,性別)

【例4.42】在xscj數據庫上產生一個結果集,包括每個專業的男生、女生人數,總人數,以及男生總數、女生總數、學生總人數。

SELECT 專業,性別,COUNT(*) AS '人數'
FROM xsb
GROUP BY CUBE(專業,性別)

【例4.43】生成一個結果集,分別根據專業和性別對人數進行聚合。

SELECT 專業,性別,COUNT(*) AS '人數'
FROM xsb
GROUP BY GROUPING SETS(專業,性別)

4.1.6 指定查詢結果分組後篩選條件:HAVING

使用GROUP BY子句和聚合函數對數據進行分組後,還可以使用HAVING子句對分組數據進行進一步的篩選。

例如,查找xscj數據庫中平均成績在85分以上的學生,就是在cjb表上按學號分組後篩選出符合平均成績大於等於85的學生。

【例4.44】查找平均成績在85分以上的學生的學號和平均成績。

SELECT 學號,AVG(成績) AS '平均成績'
FROM cjb
GROUP BY 學號
HAVING AVG(成績) >=85

說明在SELECT語句中,當WHERE、GROUP BY與HAVING子句都被使用時,要注意它們的作用和執行順序。WHERE用於篩選由FROM子句指定的數據對象,GROUP BY用於對WHERE的結果進行分組,HAVING則是對GROUP BY以後的分組數據進行過濾。

【例4.45】查找選修課程超過兩門且成績都在80分以上的學生的學號。

SELECT 學號,AVG(成績) AS '平均成績'
	FROM cjb
	WHERE 成績 > 80
	GROUP BY 學號
	HAVING COUNT(*) > 2

說明本查詢將cjb表中成績大於80的記錄按學號分組,對每一組記錄計數,選出記錄數大於2的各組的學號值並形成結果表。

【例4.46】查找通信工程專業平均成績在85分以上的學生的學號和平均成績。

SELECT 學號,AVG(成績) AS '平均成績'
FROM cjb
WHERE 學號 IN
	(
		SELECT 學號 
			FROM xsb
			WHERE 專業= '通信工程'
	)
GROUP BY 學號 HAVING AVG(成績)>=85

說明(1)先執行WHERE查詢條件中的子查詢,得到通信工程專業所有學生的學號集。然後對cjb表中的每一條記錄,判斷其“學號”字段值是否在前面所求得的學號集中。若否,則跳過該記錄,繼續處理下一條記錄;若是,則加入WHERE的結果集。

(2)對cjb表均篩選完後,按學號進行分組,再在各分組記錄中選出平均成績值大於等於85的記錄並形成最後的結果集。

4.1.7 指定查詢結果排序順序:ORDER BY 

在應用中經常要對查詢的結果排序輸出,如將學生成績由高到低排序。在SELECT語句中,使用ORDER BY子句對查詢結果進行排序。ORDER BY子句的格式爲:

其中,“排序表達式”可以是列名、表達式或一個正整數,當它是一個正整數時,表示按表中該位置上的列排序。“排序名”是Windows排序規則名稱或SQL排序規則名稱。關鍵字ASC表示升序排列,DESC表示降序排列,系統默認值爲ASC。

1. 對查詢的結果排序輸出

【例4.47】將通信工程專業的學生按出生時間先後順序排序。

SELECT * 
FROM xsb
WHERE 專業='通信工程'
ORDER BY 出生時間

例4.48】將計算機專業學生的“計算機基礎”課程成績按降序排列。

SELECT 姓名,課程名,成績
FROM xsb,kcb,cjb
WHERE xsb.學號= cjb.學號
	AND cjb.課程號=kcb.課程號
	AND 課程名='計算機基礎'
	AND 專業= '計算機'
ORDER BY 成績 DESC

 

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