在一个结果组中搜索
子选择的理念很简单一个选择查询安置在另一个查询内部创建一个在单一声明搜索中不可用的资源子选择允许查询的合并结果组比较的责任落到了数据库中而不是应用软件代码中
使用这个功能的一个途径是对两个表格中的可比数据专栏中的值进行定位例如我的一个数据库有两个表格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关键字来从Lyric表格结果组中显示的Album表格中返回歌曲名称
我使用Lyric表格结果组来给Album表格中的结果做限定WHERE子句中的子选择部分是完全自包含的因此我不需要使用例如Albumsong_name和Lyricsong_name等完整的专栏名称我没有从最终结果组的Lyric表格中返回任何值如果我需要歌曲的Lyric我会使用一个JOIN声明
使用NOT IN排除结果
你可以使用NOT IN关键字来获得明确地不被包含在另一个结果组中的结果例如我想要通过下面的代码来返回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结果组中没有出现的Album结果组返回了所有歌曲较之于返回两个查询并使用代码来比较数组你通过一个单独的声明就可以得到确切的结果
使用EXISTS来相关结果
有时你可以通过多种途径来访问相同的数据而且你需要对你的结果进行匹配(或相关)来得到值的交叉区例如我可以通过搜索Album表格来得到Metallica的歌曲列表可是我也可以从我的Cover表格中得到由Damage Inc表演的Metallica的歌曲的列表我可以在两个表格中直接比较查询结果来对值作相关
SELECT Albumsong_name FROM Album
WHERE Albumband_name = Metallica
AND EXISTS
(SELECT Coversong_name FROM Cover
WHERE Coverband_name = Damage Inc
AND Coversong_name = Albumsong_name);
在SQL代码中我使用完整的专栏名称这是因为我直接对两个表格作比较而不仅仅是将结果组作为一个被动资源来使用我并不从Cover表格中返回结果一些数据库支持NOT EXISTS关键字来确保你并没有匹配
使用合计函数来比较
除了使用子选择在相关的表格中检查数据你还可以在一个WHERE子选择中使用合计函数来确定主结果组例如我想要核实每一个Metallica歌曲在Album表格中的条目而且我还想返回缺少歌曲的专辑的名称很方便地AlbumInfo表格包含的一个专栏(album_tracks)给出了应该有多少首歌曲方面的信息
SELECT AlbumInfoalbum_name FROM AlbumInfo
WHERE AlbumInfoband_name = Metallica
AND album_tracks <>
(SELECT COUNT(*) FROM Album
WHERE Albumalbum_name = AlbumInfoalbum_name);
现在我已经成功地返回了所有Metallica的专辑中应有的曲目数量与Album表格中实际的歌曲条目数量不符的专辑名称
返回子选择结果
如果我还是关心每一张专辑的曲目数量并需要得到一个比较报告怎么办?你可以将一个子选择的结果作为最终结果组的一部分来返回这个功能经常被合计函数所使用通常地对其他表格的访问可以作为你的查询的一部分下一个例子将返回每一张Metallica的专辑应该包括的曲目数量和在Album表格中包括的条目数量
SELECT AlbumInfoalbum_name album_tracks
(SELECT COUNT(*) FROM Album
WHERE Albumalbum_name = AlbumInfoalbum_name)
FROM AlbumInfo
WHERE AlbumInfoband_name = Metallica;
另一个强有力的例子涉及了在AlbumInfo表格中将album_tracks值改变为在Album表格中实际的条目数量
UPDATE AlbumInfo SET album_tracks =
SELECT COUNT(*) FROM Album
WHERE AlbumInfoalbum_name = Albumalbum_name)
WHERE AlbumInfoband_name = Metallica;
在上两个例子中的子选择声明被看作一个自包含单位来执行
子选择比较关键字(ALL SOME ANY)
除了使用标准查询功能还有三个关键字可以使你将一个表达式值和一个单栏子选择声明结果组作比较这些关键字返回TRUE或FALSE的Boolean值ALL关键字要求子选择中所有值都遵守比较运算符SOME和ANY关键字则要求至少一对这里是ALL关键字的一个简单实例
SELECT * FROM AlbumSales
WHERE album_gross >
ALL (SELECT album_costs FROM AlbumProduction);
上面的例子将从AlbumSales表格返回在AlbumProduction表格里面付出总额大于成本而生产最昂贵的专辑的所有记录如果用ANY替代ALL声明将返回所有付出总额大于最低专辑成本的专辑记录声明= ANY与IN关键字意义是相同的声明<> ALL与NOT IN关键字是对等的关键字ANY和SOME也是等同的数据库生产商中对这些关键字的支持情况是不同的因此在出现问题时要相信查阅生产商方面的资料