跟我學(xué)SQL:(三)使用SQL子選擇來(lái)合并查詢
2024-07-21 02:31:04
供稿:網(wǎng)友
你是否曾經(jīng)為了得到所需要的信息而反復(fù)查詢?子選擇,也被稱為子查詢,也許正是你在尋找的。SQL的這項(xiàng)功能使你可以在一組結(jié)果中查詢,創(chuàng)造性地給結(jié)果組加以限定,或是在向數(shù)據(jù)庫(kù)的單一調(diào)用中將結(jié)果與一個(gè)無(wú)關(guān)系的查詢做相關(guān)。這篇文章中我將給出幾個(gè)子選擇的例子并就何時(shí)使用他們進(jìn)行討論。
在一個(gè)結(jié)果組中搜索
子選擇的理念很簡(jiǎn)單:一個(gè)選擇查詢安置在另一個(gè)查詢內(nèi)部,創(chuàng)建一個(gè)在單一聲明搜索中不可用的資源。子選擇允許查詢的合并,結(jié)果組比較的責(zé)任落到了數(shù)據(jù)庫(kù)中而不是應(yīng)用軟件代碼中。
使用這個(gè)功能的一個(gè)途徑是對(duì)兩個(gè)表格中的可比數(shù)據(jù)專欄中的值進(jìn)行定位。例如,我的一個(gè)數(shù)據(jù)庫(kù)有兩個(gè)表格,Album和Lyric。我可以很容易地通過(guò)下面的子查詢聲明來(lái)找到每一個(gè)Metallica的歌曲中包含“justice”的歌名:
SELECT song_name FROM Album
WHERE band_name = ‘Metallica’
AND song_name IN
(SELECT song_name FROM Lyric
WHERE song_lyric LIKE ‘%justice%’);
這個(gè)例子是很簡(jiǎn)單的,我從Album表格中選擇了所有Metallica的歌曲,接著,我在lyric表格中選擇所有包含“justice”的歌曲,最后,我使用IN關(guān)鍵字來(lái)從Lyric表格結(jié)果組中顯示的Album表格中返回歌曲名稱。
我使用Lyric表格結(jié)果組來(lái)給Album表格中的結(jié)果做限定。WHERE子句中的子選擇部分是完全自包含的,因此我不需要使用例如Album.song_name和Lyric.song_name等完整的專欄名稱。我沒(méi)有從最終結(jié)果組的Lyric表格中返回任何值,如果我需要歌曲的Lyric,我會(huì)使用一個(gè)JOIN聲明。
使用NOT IN排除結(jié)果
你可以使用NOT IN關(guān)鍵字來(lái)獲得明確地不被包含在另一個(gè)結(jié)果組中的結(jié)果。例如,我想要通過(guò)下面的代碼來(lái)返回Metallica在“And Justice for All”專輯中不包含單詞“justice”的歌曲:
SELECT song_name FROM Album
WHERE album_name = ‘And Justice for All’
AND band_name = ‘Metallica’
AND song_name NOT IN
(SELECT song_name FROM Lyric
WHERE song_lyric LIKE ‘%justice%’);
在前面的SQL代碼中,我選擇了Metallica的“And Justice for All,”專輯中的所有歌曲,接著是帶有歌詞中帶有“justice”所有歌曲,最后從在Lyric結(jié)果組中沒(méi)有出現(xiàn)的Album結(jié)果組返回了所有歌曲。較之于返回兩個(gè)查詢并使用代碼來(lái)比較數(shù)組,你通過(guò)一個(gè)單獨(dú)的聲明就可以得到確切的結(jié)果。
使用EXISTS來(lái)相關(guān)結(jié)果
有時(shí)你可以通過(guò)多種途徑來(lái)訪問(wèn)相同的數(shù)據(jù),而且你需要對(duì)你的結(jié)果進(jìn)行匹配(或相關(guān))來(lái)得到值的交叉區(qū)。例如,我可以通過(guò)搜索Album表格來(lái)得到Metallica的歌曲列表,可是,我也可以從我的Cover表格中得到由Damage, Inc表演的Metallica的歌曲的列表,我可以在兩個(gè)表格中直接比較查詢結(jié)果來(lái)對(duì)值作相關(guān)。
SELECT Album.song_name FROM Album
WHERE Album.band_name = ‘Metallica’
AND EXISTS
(SELECT Cover.song_name FROM Cover
WHERE Cover.band_name = ‘Damage, Inc.’
AND Cover.song_name = Album.song_name);
在SQL代碼中,我使用完整的專欄名稱,這是因?yàn)槲抑苯訉?duì)兩個(gè)表格作比較,而不僅僅是將結(jié)果組作為一個(gè)被動(dòng)資源來(lái)使用。我并不從Cover表格中返回結(jié)果。一些數(shù)據(jù)庫(kù)支持NOT EXISTS關(guān)鍵字來(lái)確保你并沒(méi)有匹配。
使用合計(jì)函數(shù)來(lái)比較
除了使用子選擇在相關(guān)的表格中檢查數(shù)據(jù),你還可以在一個(gè)WHERE子選擇中使用合計(jì)函數(shù)來(lái)確定主結(jié)果組。例如,我想要核實(shí)每一個(gè)Metallica歌曲在Album表格中的條目。而且,我還想返回缺少歌曲的專輯的名稱。很方便地,AlbumInfo表格包含的一個(gè)專欄(album_tracks)給出了應(yīng)該有多少首歌曲方面的信息。
SELECT AlbumInfo.album_name FROM AlbumInfo
WHERE AlbumInfo.band_name = ‘Metallica’
AND album_tracks <>
(SELECT COUNT(*) FROM Album
WHERE Album.album_name = AlbumInfo.album_name);
現(xiàn)在我已經(jīng)成功地返回了所有Metallica的專輯中,應(yīng)有的曲目數(shù)量與Album表格中實(shí)際的歌曲條目數(shù)量不符的專輯名稱。
返回子選擇結(jié)果
如果我還是關(guān)心每一張專輯的曲目數(shù)量并需要得到一個(gè)比較報(bào)告怎么辦?你可以將一個(gè)子選擇的結(jié)果作為最終結(jié)果組的一部分來(lái)返回。這個(gè)功能經(jīng)常被合計(jì)函數(shù)所使用。通常地,對(duì)其他表格的訪問(wèn)可以作為你的查詢的一部分。下一個(gè)例子將返回每一張Metallica的專輯,應(yīng)該包括的曲目數(shù)量和在Album表格中包括的條目數(shù)量:
SELECT AlbumInfo.album_name, album_tracks,
(SELECT COUNT(*) FROM Album
WHERE Album.album_name = AlbumInfo.album_name)
FROM AlbumInfo
WHERE AlbumInfo.band_name = ‘Metallica’;
另一個(gè)強(qiáng)有力的例子涉及了在AlbumInfo表格中將album_tracks值改變?yōu)樵贏lbum表格中實(shí)際的條目數(shù)量:
UPDATE AlbumInfo SET album_tracks =
SELECT COUNT(*) FROM Album
WHERE AlbumInfo.album_name = Album.album_name)
WHERE AlbumInfo.band_name = ‘Metallica’;
在上兩個(gè)例子中的子選擇聲明被看作一個(gè)自包含單位來(lái)執(zhí)行。
子選擇比較關(guān)鍵字(ALL, SOME, ANY)
除了使用標(biāo)準(zhǔn)查詢功能,還有三個(gè)關(guān)鍵字可以使你將一個(gè)表達(dá)式值和一個(gè)單欄子選擇聲明結(jié)果組作比較,這些關(guān)鍵字返回TRUE或FALSE的Boolean值。ALL關(guān)鍵字要求子選擇中所有值都遵守比較運(yùn)算符。SOME和ANY關(guān)鍵字則要求至少一對(duì)。這里是ALL關(guān)鍵字的一個(gè)簡(jiǎn)單實(shí)例。
SELECT * FROM AlbumSales
WHERE album_gross >
ALL (SELECT album_costs FROM AlbumPRoduction);
上面的例子將從AlbumSales表格返回在AlbumProduction表格里面付出總額大于成本而生產(chǎn)最昂貴的專輯的所有記錄。如果用ANY替代ALL,聲明將返回所有付出總額大于最低專輯成本的專輯記錄。聲明= ANY與IN關(guān)鍵字意義是相同的。聲明<> ALL與NOT IN關(guān)鍵字是對(duì)等的。關(guān)鍵字ANY和SOME也是等同的。數(shù)據(jù)庫(kù)生產(chǎn)商中對(duì)這些關(guān)鍵字的支持情況是不同的,因此在出現(xiàn)問(wèn)題時(shí)要相信查閱生產(chǎn)商方面的資料。
誰(shuí)對(duì)標(biāo)準(zhǔn)化數(shù)據(jù)結(jié)構(gòu)有疑問(wèn)?
子選擇查詢句法是簡(jiǎn)單易懂的,而懂得何時(shí)使用它卻是一個(gè)難點(diǎn)。如果你曾經(jīng)在標(biāo)準(zhǔn)化數(shù)據(jù)結(jié)構(gòu)方面出現(xiàn)問(wèn)題,子選擇聲明將幫助你獲得更深入的了解。