跟我學(xué)SQL:(三)使用SQL子選擇來合并查詢

字號:

你是否曾經(jīng)為了得到所需要的信息而反復(fù)查詢?子選擇,也被稱為子查詢,也許正是你在尋找的。SQL的這項功能使你可以在一組結(jié)果中查詢,創(chuàng)造性地給結(jié)果組加以限定,或是在向數(shù)據(jù)庫的單一調(diào)用中將結(jié)果與一個無關(guān)系的查詢做相關(guān)。這篇文章中我將給出幾個子選擇的例子并就何時使用他們進行討論。
    在一個結(jié)果組中搜索
    子選擇的理念很簡單:一個選擇查詢安置在另一個查詢內(nèi)部,創(chuàng)建一個在單一聲明搜索中不可用的資源。子選擇允許查詢的合并,結(jié)果組比較的責(zé)任落到了數(shù)據(jù)庫中而不是應(yīng)用軟件代碼中。
    使用這個功能的一個途徑是對兩個表格中的可比數(shù)據(jù)專欄中的值進行定位。例如,我的一個數(shù)據(jù)庫有兩個表格,Album和Lyric。我可以很容易地通過下面的子查詢聲明來找到每一個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%’);
    這個例子是很簡單的,我從Album表格中選擇了所有Metallica的歌曲,接著,我在lyric表格中選擇所有包含“justice”的歌曲,最后,我使用IN關(guān)鍵字來從Lyric表格結(jié)果組中顯示的Album表格中返回歌曲名稱。
    我使用Lyric表格結(jié)果組來給Album表格中的結(jié)果做限定。WHERE子句中的子選擇部分是完全自包含的,因此我不需要使用例如Album.song_name和Lyric.song_name等完整的專欄名稱。我沒有從最終結(jié)果組的Lyric表格中返回任何值,如果我需要歌曲的Lyric,我會使用一個JOIN聲明。
    使用NOT IN排除結(jié)果
    你可以使用NOT IN關(guān)鍵字來獲得明確地不被包含在另一個結(jié)果組中的結(jié)果。例如,我想要通過下面的代碼來返回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é)果組中沒有出現(xiàn)的Album結(jié)果組返回了所有歌曲。較之于返回兩個查詢并使用代碼來比較數(shù)組,你通過一個單獨的聲明就可以得到確切的結(jié)果。
    使用EXISTS來相關(guān)結(jié)果
    有時你可以通過多種途徑來訪問相同的數(shù)據(jù),而且你需要對你的結(jié)果進行匹配(或相關(guān))來得到值的交叉區(qū)。例如,我可以通過搜索Album表格來得到Metallica的歌曲列表,可是,我也可以從我的Cover表格中得到由Damage, Inc表演的Metallica的歌曲的列表,我可以在兩個表格中直接比較查詢結(jié)果來對值作相關(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代碼中,我使用完整的專欄名稱,這是因為我直接對兩個表格作比較,而不僅僅是將結(jié)果組作為一個被動資源來使用。我并不從Cover表格中返回結(jié)果。一些數(shù)據(jù)庫支持NOT EXISTS關(guān)鍵字來確保你并沒有匹配。
    使用合計函數(shù)來比較
    除了使用子選擇在相關(guān)的表格中檢查數(shù)據(jù),你還可以在一個WHERE子選擇中使用合計函數(shù)來確定主結(jié)果組。例如,我想要核實每一個Metallica歌曲在Album表格中的條目。而且,我還想返回缺少歌曲的專輯的名稱。很方便地,AlbumInfo表格包含的一個專欄(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);