SQL乐园(22):嵌套查询

软件世界

  不管是对单个表进行查询还是对多个表进行查询,FROM子句后面的查询对象,也就是数据的源头,都是数据表。那么数据源能否不是数据表呢?可以。SELECT语句中的数据源可以是数据表、视图,也可以是另外的SELECT语句。

  为什么要引进嵌套查询

  在规划一个数据库时,为了减少冗余数据,除了主键以外,不同的表之间很少有相同的字段,这就产生了这样一种矛盾:我们需要的信息可能在任何一个表中都无法找到。这时一种很容易想到的解决方法就是:先执行一个查询并把结果集保存在表A中,然后再执行一个查询并把结果集保存在表B中,最后对A和B进行联合查询。

  可是这种解决方法有几个明显的缺点。

  1.效率低。尤其是在客户端对远程数据库进行查询时,这种方法的效率是很低的,执行过程耗时很长。

  2.安全性差。因为要执行几次查询,那么在查询的间隙,如果数据库有变化,则最后的查询结果很有可能会产生错误。虽然我们可以先锁定这些表(这样,在整个查询期间,表不能被修改),但是这样的话,会给数据库的其他操作带来影响和风险。

  什么是嵌套查询

  嵌套查询也叫子查询,而由嵌套查询得到的结果一般叫作动态表。下面我们来看一个例子:有个商店建有一个销售数据表Sale(货物名称ProductName、售出货物数量Quantity、货物价格ProductPrice),查询要求是列出货物名称和该类货物销售额占商店总销售额的比例。

  一种“想当然”的做法是:SELECT Pro ductName, (Quan tity*ProductPrice)/SUM(Quantity*ProductPrice) FROM Sale GROUP BY ProductName, Quantity, ProductPrice

  但是一执行起来就会发现这种方法根本行不通,算出来的比例都是1。

  其实用嵌套查询可以解决这个问题:

  SELECT Pro ductName, A.Salesof Product/B.SalesSum AS Per FROM

  (SELECT ProductName, SUM(Quanti ty*ProductPrice) AS SalesofProduct FROM Sale GROUP BY ProductName) AS A

  CROSS JOIN

  (SELECT SUM(Quantity*ProductPrice) AS SalesSum FROM Sale) AS B

  ORDER BY A. ProductName

  上例中我们使用了两个嵌套查询,分别得到每种货物的名称、销售额和商店总销售额,然后再对两个子查询得到的结果集进行交叉连接,最后计算出结果。请朋友们仔细分析上句SQL语句的层次。

  预告:下期我们一起学习GROUP BY数据分组子句。

  上期问题:在Northwind数据库products表中按产品编号为序列出所有产品的主要信息(产品编号productID、产品名称productname、价格Unitprice),并把“orderdetails”表中卖出价(Unitprice)与products表中定价(Unitprice)相同的订单编号列出来。

  参考答案:select A.productID,A.productname,A.Unit price,B.orderID

  from products as A left outer join “order details” AS B

  on(A.productID=B.productID and A.Unitprice=B.Unit price) order by A.productID

  本期问题:在Northwind数据库“order details”表中,找出ProductID为2的商品的产品编号、订单编号和每份订单数额在该商品订单总额中的比例。

  本期的幸运读者是四川的马宇文,他将获得《全民学电脑──电脑入门》(含1CD)一本。请朋友们在答题的E-mail中注明通讯地址,以便邮寄奖品。