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中注明通讯地址,以便邮寄奖品。