Collection Contents 上一页 下一页 PDF

ASA SQL 用户指南

使用子查询

子查询和连接


子查询优化程序会自动将使用子查询的多个查询改写为连接。

示例 

请看以下请求:[Clarke 女士和 Suresh 女士何时下的订单,并且是向哪些销售代表下的订单?] 可以用以下查询回答上述请求:

SELECT order_date, sales_rep
FROM sales_order
WHERE cust_id IN (
   SELECT id
   FROM customer
   WHERE lname = 'Clarke' OR fname = 'Suresh')
Order_date sales_rep
2001-01-05 1596
2000-01-27 667
2000-11-11 467
2001-02-04 195
... ...

该子查询生成与其姓名在 WHERE 子句中列出的两个客户相对应的客户 ID 的列表,并且主查询查找与这两位女士的订单相对应的订单日期和销售代表。

用连接替代子查询 

可以使用连接回答同样的问题。下面是该查询的使用了两表式连接的替代形式:

SELECT order_date, sales_rep
FROM sales_order, customer
WHERE cust_id=customer.id AND
  (lname = 'Clarke' OR fname = 'Suresh')

此查询形式将 sales_order 表连接到 customer 表,以查找每一客户的订单,然后只返回 Suresh 和 Clarke 的那些记录。

某些连接无法被改写为子查询 

这两个查询都会找到正确的订单日期和销售代表,并且都同样正确。许多人会认为子查询形式更为自然,因为该请求没有询问与客户 ID 有关的任何信息,并且因为将 sales_order 和 customer 表连接在一起来回答该问题看起来似乎有一些奇怪。

但是,如果将该请求更改为包括来自 customer 表的某些信息,则该子查询形式将不再有效。例如,如果请求是 [Clarke 女士和 Suresh 女士是何时下的订单、向哪些销售代表下的订单以及这两位女士的全名是什么?],则需要在主 WHERE 子句中包括 customer 表:

SELECT fname, lname, order_date, sales_rep
FROM sales_order, customer
WHERE cust_id=customer.id AND (lname = 'Clarke' OR fname = 'Suresh')
fname lname order_date sales_rep
Belinda Clarke 1/5/01 1596
Belinda Clarke 1/27/00 667
Belinda Clarke 11/11/00 467
Belinda Clarke 2/4/01 195
... ... ... ...
某些子查询无法被改写为连接 

同样,在某些情况下,可以使用子查询,但无法使用连接。例如:

SELECT name, description, quantity
FROM product
WHERE quantity <  2 * (
   SELECT avg(quantity)
   FROM sales_order_items)
name description quantity
Tee Shirt Tank Top 28
Baseball Cap Wool cap 12
Visor Cloth Visor 36
... ... ...

在此例中,内部查询是汇总查询,而外部查询不是汇总查询,因此,无法通过一个简单连接来合并这两个查询。

有关连接的详细信息,请参见连接:从多个表检索数据


Collection Contents 上一页 下一页 PDF