ANY 关键字 在子查询前面使用关键字 ANY (或它的同义词 SOME)来确定是否对至少一个返回值的 比较为 true 。如果子查询不返回任何值,那么搜索条件为false。(因为没有值存在,所以 对于其中一个值条件不能为 true 。) 以下查询查找包含总价大于订单号 1005 中任何一个商品总价的商品的所有订单的订单 号。 图: 查询 SELECT DISTINCT order_num FROM items WHERE total_price > ANY (SELECT total_price FROM items WHERE order_num = 1005); 图: 查询结果 order_num
1001 1002 1003 1004 ⋮ 1020 1021 1022 1023
GBase 8s SQL 指南:教程 南大通用数据技术股份有限公司 - 136 -
单值子查询 如果您知道子查询可能对外部级别查询返回刚好一个值,那么不需要 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) 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
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 子句中, 只有不相关子查询才是有效的。
EXISTS 关键字 关键字 EXISTS 也被称为存在限定符,因为仅当外部 SELECT(如下所示)找到至少一行 时,子查询才为 true 。 图: 查询 SELECT UNIQUE manu_name, lead_time FROM manufact 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*')
GBase 8s SQL 指南:教程 南大通用数据技术股份有限公司 - 139 -
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);
SELECT customer_num, company FROM customer WHERE NOT EXISTS (SELECT * FROM orders WHERE customer.customer_num = orders.customer_num); 查询中的每个语句返回下列行,这些行标识尚未下订单的客户。 图: 查询结果 customer_num company
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