您的位置:首页 > 数据库

轻松掌握用SQL来合并查询

2010-06-14 14:35 162 查看
轻松掌握用SQL来合并查询

  你是否曾经为了得到所需要的信息而反复查询?子选择,也被称为子查询,也许正是你在寻找的。SQL的这项功能使你可以在一组结果中查询,创造性地给结果组加以限定,或是在向数据库的单一调用中将结果与一个无关系的查询做相关。这篇文章中将给出几个子选择的例子并就何时使用他们进行讨论。
  在一个结果组中搜索
  子选择的理念很简单:一个选择查询安置在另一个查询内部,创建一个在单一声明搜索中不可用的资源。子选择允许查询的合并,结果组比较的责任落到了数据库中而不是应用软件代码中。
  使用这个功能的一个途径是对两个表格中的可比数据专栏中的值进行定位。例如,我的一个数据库有两个表格,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子句中的子选择部分是完全自包含的,因此我不需要使用例如Album.song_name和Lyric.song_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 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代码中,我使用完整的专栏名称,这是因为我直接对两个表格作比较,而不仅仅是将结果组作为一个被动资源来使用。我并不从Cover表格中返回结果。一些数据库支持NOT EXISTS关键字来确保你并没有匹配。
  使用合计函数来比较
  除了使用子选择在相关的表格中检查数据,你还可以在一个WHERE子选择中使用合计函数来确定主结果组。例如,我想要核实每一个Metallica歌曲在Album表格中的条目。而且,我还想返回缺少歌曲的专辑的名称。很方便地,AlbumInfo表格包含的一个专栏(album_tracks)给出了应该有多少首歌曲方面的信息。
以下是引用片段:
  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);
  现在我已经成功地返回了所有Metallica的专辑中,应有的曲目数量与Album表格中实际的歌曲条目数量不符的专辑名称。
  返回子选择结果
  如果我还是关心每一张专辑的曲目数量并需要得到一个比较报告怎么办?你可以将一个子选择的结果作为最终结果组的一部分来返回。这个功能经常被合计函数所使用。通常地,对其他表格的访问可以作为你的查询的一部分。下一个例子将返回每一张Metallica的专辑,应该包括的曲目数量和在Album表格中包括的条目数量:
以下是引用片段:
  SELECT AlbumInfo.album_name, album_tracks,
  (SELECT COUNT(*) FROM Album
  WHERE Album.album_name = AlbumInfo.album_name)
  FROM AlbumInfo
  WHERE AlbumInfo.band_name = ‘Metallica’;
  另一个强有力的例子涉及了在AlbumInfo表格中将album_tracks值改变为在Album表格中实际的条目数量:
以下是引用片段:
  UPDATE AlbumInfo SET album_tracks =
  SELECT COUNT(*) FROM Album
  WHERE AlbumInfo.album_name = Album.album_name)
  WHERE AlbumInfo.band_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也是等同的。数据库生产商中对这些关键字的支持情况是不同的,因此在出现问题时要相信查阅生产商方面的资料。
解析SQL Server identity列的操作方法
2007-09-20 15:28 作者: 佚名 出处: 论坛整理 责任编辑:幽灵
  SQL Server中,经常会用到Identity标识列,这种自增长的字段操作起来的确是比较方便。但它有时还会带来一些麻烦。
  示例一:当表中被删除了某些数据的时候,自增长列的编号就不再是一个连线的数列,这种时候我们可以用以下方案来解决。
以下是引用片段:
  SET IDENTITY_INSERT [ON|OFF]
  允许将显式值插入表的标识列中,当设置为ON时,这时可能在INSERT操作时手工指定插入到标识列中的编号,同时必须在操作完成后,将IDENTITY_INSERT还原成OFF,否则下次插入的时候必须指定编号,那不然就无法完成INSERT操作。
  示例二:当表中的记录被全部删除,但此时标识列的值越来越大的时候,如果不加以重置,它还会无休止的增长。这个时候我们就要用到:
以下是引用片段:
  DBCC CHECKIDENT(TABLE, [RESEED|NORESEED], [1])
  将把指定表的种子值强制重设为1。然而,你可能不想将种子重设为1,在这种情况下,你可以用你想用的种子值替代第三个参数。有时候你可能想知道当前的种子,而不是想重设种子,这时你就要用到NORESEED,而不用再去顾忌第三个参数。
巧用一条SQL语句实现其它进制到十进制转换
2007-09-25 11:10 作者: han 出处: 论坛整理 责任编辑:幽灵
  巧用一条SQL语句实现其它进制到十进制转换,具体实现方法如下:
  -----二进制转换十进制-----------------
以下是引用片段:
  select sum(data1)
  from (select substr('1101', rownum, 1) * power
  (2, length('1101') - rownum) data1
  from dual
  connect by rownum <= length('1101'))
  -----八进制转换十进制-----------------
以下是引用片段:
  select sum(data1)
  from (select substr('1101', rownum, 1) * power
  (8, length('1101') - rownum) data1
  from dual
  connect by rownum <= length('1101'))
  -----十六进制转换十进制-----------------
以下是引用片段:
  select sum(data1)
  from (select (CASE upper(substr('2D', rownum, 1))
  WHEN 'A' THEN '10'
  WHEN 'B' THEN '11'
  WHEN 'C' THEN '12'
  WHEN 'D' THEN '13'
  WHEN 'E' THEN '14'
  WHEN 'F' THEN '15'
  ELSE substr('2D', rownum, 1)
  END) * power(16, length('2D') - rownum) data1
  from dual
  connect by rownum <= length('2D'))
  注释:
  对其它进制可以根据例子将power的底数改成相应的进制就可以了。
  本文只是一个例子,大家可以把它封装成一个通用函数进行实用。
  大家在试的时候将里面相应的其它进制的数值换成自己的数据就可以了(有多处)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: