合並多個結果集 SQL語言的高級用法


GPS平台、網站建設、軟件開發、系統運維,找森大網絡科技!
https://cnsendnet.taobao.com
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=2060

 

合並多個結果集 SQL語言的高級用法

第二章 SQL語言的高級用法

2.8 合並多個結果集
  UNION 操作符可以把兩個或多個SELECT語句的結果集合並起來。
  當你想查詢的數據在不同的地方,並且無法由一個查詢語句得到時,你可以使用操作符UNION。使用操作符UNION時,要注意下列注意事項和原則:

􀂋 SQLServer要求UNION子句中引用的所有表都具有相似的數據類型、相同的字段數,並且在每個查詢中,選擇列表里字段的順序也必須相同。 􀂋 SQL Server將自動刪除結果集中的重復記錄。但是,如果你指定了選項ALL,結果集中的所有記錄都將被返回。 􀂋 你必須在第一個SELECT語句中指定字段名。因此如果你想為結果集定義新的字段名,你必須在第一個SELECT語句中創建字段別名。 􀂋 如果你希望結果集中的記錄按一定順序排列,你必須在UNION子句中用ORDER BY指定排序方式。否則,結果集中記錄的順序就可能不是你希望得到的。 􀂋 你可以把一個復雜的查詢分解成若干個SELECT語句,並用操作符UNION合並結果集,這樣你會發現查詢速度會有所提高。

  下面的例子合並了兩個結果集。第一個結果集從表customers中返回每個顧客的字段姓名、城市和郵政編碼。第二個結果集從表employees中返回每個雇員的姓名、城市和郵政編碼。當使用操作符UNION合並這兩個結果集時,請注意第一個結果集中所指定的字段的別名。

USE northwind
SELECT( firstname+ ‘’+ lastname ) AS name,city,postalcode
FROM employees
UNION
SELECT companyname,city,postalcode
FROM customers
GO
運行結果:
name city postalcode
Alfreds Futterkiste Berlin 12209
Ana Trujillo Emparedados y helados México D.F. 05021
Antonio Moreno Taquería México D.F. 05023
Around the Horn London WA1 1DP
(100row(s)affected)

 

第二章 SQL語言的高級用法

2.9 子查詢介紹
一個查詢語句嵌套在一個SELECT語句、INSERT語句、UPDATE語句、DELETE語句或其他的子查詢語句時,則稱這個語句為子查詢(subqueries)。你通常可以用連接語句(JOIN)代替一個子查詢,你也可以用一個子查詢代替一個表達式。
子查詢可以把一個復雜的查詢分解成一系列的邏輯步驟,這樣就可以用一個單個的語句解決一個復雜的查詢問題。當查詢依賴於另一個查詢的結果時,子查詢會很有用。
一般情況下,包含子查詢的查詢語句也可以被寫作連接語句。查詢語句,不論含有連接還是子查詢,它們的執行效率都差不多。當查詢優化器遇到子查詢語句時,通過用語法上類似的連接語句代替這個子查詢,因此子查詢和連接語句具有相同的執行計划,經過這樣的優化步驟后,連接與子查詢的執行效率將大同小異。區別在於子查詢可能要求查詢優化器執行額外的操作,例如排序,而這些操作將會影響查詢的處理策略。
連接將使查詢優化器以效率最高地方式查詢數據,如果查詢不要求多個步驟,就不需要使用子查詢。
當你決定要使用子查詢時,應注意以下事項:


􀂋 子查詢要用括號括起來; 􀂋 只要需要一個值或一系列的值,你就可以用子查詢代替一個表達式。可以用子查詢返回一個含有多個字段的結果集,這個表可以代替一個表或完成一個連接語句的操作; 􀂋 子查詢不能查詢包含數據類型是text或image的字段; 􀂋 子查詢中也可以再包含子查詢,嵌套可以多至32層。

2.9.1 把子查詢用作派生的表
可以用子查詢產生一個派生的表,用於代替FROM子句中的表。派生表是FROM子句中子查詢的一個特殊用法,用一個別名或用戶自定義的名字來引用這個派生表。FROM子句中的子查詢將返回一個結果集,這個結果集所形成的表將被外層SELECT語句使用。
在下面的例子中,內層查詢用子查詢產生了一個派生的表,外層查詢將使用內層查詢的結果集。在功能上,派生表本身就等同於一個完整的查詢,但為了便於說明,把派生表獨立出來。

USE northwind
SELECT T.orderid, T.Customerid
FROM ( SELECT orderid,customerid
FROM orders) AS T
GO

當用子查詢產生派生表時,必須考慮到:

􀂋 查詢語句中的一個結果集,被用做一個表; 􀂋 代替了FROM子句中的表; 􀂋 將與查詢的其它部分一起參與優化。

2.9.2 把子查詢用作表達式
在Transact-SQL中,所有使用表達式的地方,都可以用子查詢代替。此時子查詢必須返回一個單個的值或某一個字段的值。子查詢可以返回一系列的值來代替出現在WHERE子句中的IN關鍵字的表達式。
當子查詢被用作表達式時,必須考慮到:

􀂋 被當作一個表達式處理並計算。查詢優化器總是將一個表達式等同於連接一個只有一行記錄的表; 􀂋 在整個語句中,只執行一次。

下面的例子返回一本暢銷的計算機書的價格,所有書的平均價格,及該書和所有書的平均價格的差價。

USE pubs ·
SELECT title,price
,(SELECT AVG (price) FROM titles) AS average
,price - (SELECT AVG (price) FROM titles ) AS difference
FROM titles
WHERE type = popular_comp’
GO

2.9.3 用子查詢關聯數據
相關子查詢可被用作動態表達式,這個表達式的值相對於外層查詢的每一行而變化。
查詢處理器為外層查詢的每一個記錄計算子查詢的值,一次一行,而這個子查詢每次都會被作為一個表達式而被計算並返回給外層查詢。相關子查詢是動態執行的子查詢和外層查詢間的一個非常有效的組合。
通常,一個查詢可以寫成多種方式,但得到的結果都相同。相關子查詢把一個復雜的查詢分解成為兩個或多個簡單的、相關的查詢。
使用相關子查詢時,內層子查詢被反復執行,對外層查詢的每一行,內層查詢就要執行一次。

􀂋 SQLSewer為外層查詢的每一條記錄執行一次內層查詢; 􀂋 SQLSewer將比較內層查詢的結果和外層查詢的結果。

下面的例子返回訂購了23號產品20件以上的顧客的列表:

USE northwind
SELECT orderid, customerid
FROM orderS AS or1
WHERE 20 < (SELECT quantity
FROM [Order details] AS od
WHERE or1.orderid = od.orderid AND od.productid = 23)
GO
運行結果:
orderid customerid
10337 FRANK
10348 WANDK
10396 FRANK
10402 ERNSH
10462 CONSH
(11 row(s) affected)



下面的例子從表orderdetails中返回每種產品訂購數量最多的列表。請注意這里的相關子查詢和外層查詢引用了同一個表,查詢優化器通常把這當作一個子連接。

USE northwind
SELECT DISTINCT productid,quantity
FROM [order details] AS ordl
WHERE quantity = (SELECT MAX (quantity)
FROM [order details] AS ord2
WHERE ordl.productid:ord2.productid)
GO
運行結果:
productid quantity
50 40
67 40
4 50
9 50
11 50
(77row(s)affected)

2.9.4 模擬連接子句
你可以用一個相關子查詢產生一個結果集,這個結果集與連接(JOIN)所產生的結果集是相同的,例如,從某個表中查詢數據,然后從外層查詢中引用這個表。
下面的例子用相關子查詢搜索被多個出版商出版的書的類型。為了防止語法的混亂不清,要求使用表的別名,用以區分兩個titles表各自代表的含義。

USE pubs
SELECT DISTINCT t1.type
FROM titles AS t1
WHERE t1.type IN
(SELECT t2.type
FROM titles AS t2
WHERE t1.pub_id <> t2.pub_id)
GO
運行結果:
Type
business
psychology
(2 row(s) affected)

下面的例子所返回的結果集與前面的例子相同,但使用的不是相關子查詢,而是子查詢。

USE pubs
SELECT DISTINCT t1.type
FROM titles AS tl
INNER JOIN titles AS t2
ON t1.type = t2.type
WHERE t1.pub_id <> t2.pub_id
GO

2.9.5 模擬HAVING子句
相關子查詢產生的結果集可以模擬HAVING子句產生的結果集。
下面的例子查詢同類書中價格大於平均價格的所有書的書名。對於t1中每一個可能的記錄,SQL Server都將執行這個子查詢,如果某條記錄的價格大於計算出的平均價格,就把這條記錄放到結果集中。你不需要在語句中顯式地使用分組語句,因為計算平均價格的子查詢中,WHERE子句已經對書的類型進行了限制。

USE pubs
SELECT t1.type,t1.title,t1.price
FROM titles AS t1
WHERE t1.price > ( SELECT AVG(t2.price) FROM titles AS t2
WHERE t1.type = t2.type)
GO
運行結果:
Resulttype title
Business The Busy Executive™s Database Guide
Business Straight Talk About Computers
mod_cook Silicon Valley Gastronomic Treats
popular_comp But Is It User Friendly?
Psychology Computer Phobic AND Non-Phobic
Individuals: Behavior Variations
Psychology Prolonged Data Deprivation: Four Case
Studies
trad_cook Onions, Leeks, and Garlic: Cooking

Secrets of the Mediterranean
(7row(s)affected)

下面的例子產生的結果集和前面的例子相同,但它用的是含有GROUPBY和HAVING子句的子連接語句。

USE pubs
SELECT t1.type, t1.title, t1.price
FROM tities AS t1
INNER JOIN titles AS t2
ON t1.type = t2.type
GROUP BY t1.type,t1.title, t1.price
HAVING t1.priCe > AVG(t2.price)
GO

注意:可以用相關子查詢模擬一個JOIN和HAVING子句產生的結果集,但查詢處理器實現它們的方式可能不同。


2.9.6 使用EXISTS和NOT EXIST子句
可以用EXISTS和NOT EXISTS子句判斷某個值是否在一系列的值中。
EXISTS和NOT EXISTS子句和相關子查詢一同使用時,可以限制外層查詢,使其結果集符合子查詢的條件。基於某一條記錄是否滿足子查詢,EXISTS和NOT EXISTS子句將返回TRUE或FALSE。
當子查詢和EXISTS或NOT EXISTS子句共同使用時,SQL Server將測試數據是否匹配子查詢結果集的某一條記錄。其實並沒有返回任何記錄。當SQL Server知道至少有一條記錄滿足子查詢中的WHERE條件時,就將結束數據搜索。
當SQLServer處理一個包含EXISTS或NOTEXISTS的子查詢時:

􀂋 外層查詢測試子查詢返回的記錄是否存在; 􀂋 基於查詢所指定的條件,子查詢返回TRUE或FALSE; 􀂋 子查詢不產生任何數據。

下面的例子在WHERE子句中使用了含有EXISTS子句的相關子查詢,它將返回在2000年4月10日訂購產品的雇員。

USE northwind
SELECT lastname, employeeid
FROM employees AS e
WHERE EXISTS ( SELECT * FROM orders AS o WHERE e.employeeid = o.employeeid
AND o.orderdate = ’10/4/2000’
GO
運行結果:
IaStname empIOyeeid
Peacock 4
King 7
(2row(s)affected)

下面的例子返回的結果集和前面例子的一樣,這個例子表明你也可以用連接操作,而不是相關子查詢,達到同樣的目的。請注意這個查詢需要使用關鍵字DISTINCT,只為每個雇員產生一條記錄。

USE northwind
SELECT DISTINCT lastname, e.employeeid
FROM orders AS o
INNER JOIN employees AS e
ON o.employeeid = e.employeeid
WHERE O.Orderdate = ‘10/4/2000’
GO

 

 

GPS平台、網站建設、軟件開發、系統運維,找森大網絡科技!
https://cnsendnet.taobao.com
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=2060


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM