单值子查询 如果您知道子查询可能对外部级别查询返回刚好一个值,那么不需要 ALL 或 ANY 。可 如同对待函数一样对待只返回一个值的子查询。这种子查询通常使用聚集函数,原因是聚 集函数总是返回单个的。 下列查询在子查询中使用聚集函数 MAX 查找包括最大排球网数目的订单的 order_num。 图: 查询 SELECT order_num FROM items WHERE stock_num = 9 AND quantity = (SELECT MAX (quantity) FROM items WHERE stock_num = 9); 图: 查询结果 order_num
1012 下列查询在子查询中使用聚集函数 MIN 选择总价高于最小价格 10 倍的商品。 图: 查询 SELECT order_num, stock_num, manu_code, total_price FROM items x WHERE total_price > (SELECT 10 * MIN (total_price)
GBase 8s SQL 指南:教程 南大通用数据技术股份有限公司 - 139 - FROM items WHERE order_num = x.order_num); 图: 查询结果 order_num stock_num manu_code total_price
相关子查询 相关子查询是引用不在其 FROM 子句中的列或表的子查询。该列可以在 Projection 子句 或 WHERE 子句中。 通常,相关子查询会降低性能。建议使用表名或表别名限制子查询中的列名。从而除去与 列所驻留的表相关的任何疑问。 下列查询是相关子查询的一个示例,它返回 orders 表中 10 个最近的装运日期的列表。它 在子查询之后加上 ORDER BY 子句以对结果进行排序, 原因是 (除在 FROM 子句以外) 您不能在子查询中包括 ORDER BY 。 图: 查询 SELECT po_num, ship_date FROM orders main WHERE 10 > (SELECT COUNT (DISTINCT ship_date) FROM orders sub WHERE sub.ship_date < main.ship_date) AND ship_date IS NOT NULL ORDER BY ship_date, po_num; 因为子查询产生的数取决于 main.ship_date(外部 SELECT 产生的一个值),所以该子查 询是相关的。因此,必须对外部查询考虑的每一行重新执行子查询。 该查询使用 COUNT 函数来将值返回到主查询。然后,ORDER BY 子句对数据进行排序。 查询找到并返回具有 10 个最新装运日期的 16 行,如下所示。 图: 查询结果 po_num ship_date
4745 06/21/1998 278701 06/29/1998
GBase 8s SQL 指南:教程 南大通用数据技术股份有限公司 - 140 - 429Q 06/29/1998 8052 07/03/1998 B77897 07/03/1998 LZ230 07/06/1998 B77930 07/10/1998 PC6782 07/12/1998 DM354331 07/13/1998 S22942 07/13/1998 MA003 07/16/1998 W2286 07/16/1998 Z55709 07/16/1998 C3288 07/25/1998 KF2961 07/30/1998 W9925 07/30/1998 如果对大型表使用相关子查询(如图 1),那么应对 ship_date 列建立索引以提高性能。否 则,此 SELECT 语句效率降低,原因是它对表的每一行执行一次子查询。有关建立索引和 性能问题的信息,请参阅《GBase 8s 管理员指南》 和 GBase 8s 性能指南 。 然而,不能在 FROM 子句中使用相关子查询,如下列无效示例所示: SELECT item_num, stock_num FROM items, (SELECT stock_num FROM catalog WHERE stock_num = items.item_num) AS vtab; 该示例中的子查询具有错误 -24138: ALL COLUMN REFERENCES IN A TABLE EXPRESSION MUST REFER TO TABLES IN THE FROM CLAUSE OF THE TABLE EXPRESSION. 数据库服务器发出该错误的原因是子查询中的 items.item_num 列还出现在外部查询的 Projection 子句中,但是内部查询的 FROM 子句仅指定catalog 表。 错误消息文本中的术语 表表达式指的是 FROM 子句中的子查询返回的列值或表达式集合。而在 FROM 子句中, 只有不相关子查询才是有效的。
GBase 8s SQL 指南:教程 南大通用数据技术股份有限公司 - 141 - WHERE EXISTS (SELECT * FROM stock WHERE description MATCHES '*shoe*' AND manufact.manu_code = stock.manu_code); 通常可使用 EXISTS 来构造等价于使用 IN 的查询的查询。 下列查询使用 IN 谓词来构造 与上述返回相同结果的查询。 图: 查询 SELECT UNIQUE manu_name, lead_time FROM stock, manufact WHERE manufact.manu_code IN (SELECT manu_code FROM stock WHERE description MATCHES '*shoe*') AND stock.manu_code = manufact.manu_code; 图 1和图 2返回生产某种鞋的制造商以及预订产品的交付周期的行。 该结果显示了返回值。
图: 查询结果 manu_name lead_time
Anza 5 Hero 4 Karsten 21 Nikolus 8 ProCycle 9 Shimara 30 将关键字 NOT 添加至 IN 或 EXISTS 以创建与前面查询相反的搜索条件。也可以 用 !=ALL 代替 NOT IN。 下列查询显示了执行同一操作的两种方法。一种方法可能允许数据库服务器执行相对另一 种方法较少的工作,则会取决于数据库的设计和表的大小。要了解哪一种查询更好,使用 SET EXPLAIN 命令来获取查询计划的清单。在 GBase 8s 性能指南 和 GBase 8s SQL 指南: 语法 中讨论了 SET EXPLAIN。 图: 查询 SELECT customer_num, company FROM customer WHERE customer_num NOT IN (SELECT customer_num FROM orders WHERE customer.customer_num = orders.customer_num);
GBase 8s SQL 指南:教程 南大通用数据技术股份有限公司 - 142 - SELECT customer_num, company FROM customer WHERE NOT EXISTS (SELECT * FROM orders WHERE customer.customer_num = orders.customer_num); 查询中的每个语句返回下列行,这些行标识尚未下订单的客户。 图: 查询结果 customer_num company
102 Sports Spot 103 Phil's Sports 105 Los Altos Sports 107 Athletic Supplies 108 Quinn's Sports 109 Sport Stuff 113 Sportstown 114 Sporting Place 118 Blue Ribbon Sports 125 Total Fitness Sports 128 Phoenix University 关键字 EXISTS 和 IN 用于称为相交的集合运算, 关键 NOT EXISTS 和 NOT IN 用于称 为差异的集合运算。这些概念在集合运算中讨论。 下列查询执行对 items 表的子查询来标识 stock 表中尚未预订的所有商品。 图: 查询 SELECT * FROM stock WHERE NOT EXISTS (SELECT * FROM items WHERE stock.stock_num = items.stock_num AND stock.manu_code = items.manu_code); 该查询返回以下行。 图: 查询结果 stock_num manu_code description unit_price unit unit_descr