子查询优化程序会自动将使用子查询的多个查询改写为连接。
请看以下请求:[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 |
| ... | ... | ... |
在此例中,内部查询是汇总查询,而外部查询不是汇总查询,因此,无法通过一个简单连接来合并这两个查询。
有关连接的详细信息,请参见连接:从多个表检索数据。
SQL Anywhere Studio 9.0.2
版权所有 © 1989–2005 Sybase, Inc. 部分版权所有 © 2001–2005 iAnywhere Solutions, Inc. 保留所有权利。