EXISTS 和 NOT EXISTS
EXISTS
谓词是最常见的谓词之一,可用于构建使用非相关和相关子查询的条件。使用 EXISTS
可以不考虑数量就能识别是否存在关系。例如,如果子查询返回任何行,EXISTS
返回 true,如果子查询没有返回行,[NOT] EXISTS
返回 true。
[NOT] EXISTS
子查询采用以下格式:
expression [ NOT ] EXISTS ( subquery )
如果子查询至少返回了一个行,则认为符合 EXISTS
条件。由于结果仅取决于是否返回了记录,而不是取决于这些记录的内容,因此子查询的输出列表通常没有吸引力。常见的编码规范是按照如下方式编写所有 EXISTS
测试:
EXISTS (SELECT 1 WHERE ...)
在上述片段中,SELECT 1
为查询中所有记录返回了值 1。例如,查询返回了五个记录,它会返回 5 个一。系统不会考虑记录中的实际值;它只要知道是否返回了行。
或者,子查询使用 EXISTS
的选择列表可能包含星号 (*)。您不需要指定列名称,因为查询会测试是否有符合子查询中指定条件的记录。
EXISTS (SELECT * WHERE ...)
注意
-
如果
EXISTS (subquery)
返回至少 1 行,则结果为 TRUE。 -
如果
EXISTS (subquery)
不返回任何行,则结果为 FALSE。 -
如果
NOT EXISTS (subquery)
返回至少 1 行,则结果为 FALSE。 -
如果
NOT EXISTS (subquery)
不返回任何行,则结果为 TRUE。
示例
以下查询检索从任何一家商店购买金额超过 550 美元商品的所有客户的列表:
=> SELECT customer_key, customer_name, customer_state
FROM public.customer_dimension WHERE EXISTS
(SELECT 1 FROM store.store_sales_fact
WHERE customer_key = public.customer_dimension.customer_key
AND sales_dollar_amount > 550)
AND customer_state = 'MA' ORDER BY customer_key;
customer_key | customer_name | customer_state
--------------+--------------------+----------------
14818 | William X. Nielson | MA
18705 | James J. Goldberg | MA
30231 | Sarah N. McCabe | MA
48353 | Mark L. Brown | MA
(4 rows)
使用 EXISTS 子查询还是 IN 子查询,取决于您在外查询块和内查询块中所选择的谓词。例如,要为供应商表中有记录的供应商获取所有商店在 2003 年 1 月 2 日下的所有订单的列表:
=> SELECT store_key, order_number, date_ordered
FROM store.store_orders_fact WHERE EXISTS
(SELECT 1 FROM public.vendor_dimension
WHERE public.vendor_dimension.vendor_key = store.store_orders_fact.vendor_key)
AND date_ordered = '2012-01-02';
store_key | order_number | date_ordered
-----------+--------------+--------------
37 | 2559 | 2012-01-02
16 | 552 | 2012-01-02
35 | 1156 | 2012-01-02
13 | 3885 | 2012-01-02
25 | 554 | 2012-01-02
21 | 2687 | 2012-01-02
49 | 3251 | 2012-01-02
19 | 2922 | 2012-01-02
26 | 1329 | 2012-01-02
40 | 1183 | 2012-01-02
(10 rows)
上述查询查找是否存在下单的供应商和日期。要返回特定的值,而不是简单地确定是否存在,查询需要查找在 2004 年 1 月 4 日达成最佳交易的供应商所下的订单。
=> SELECT store_key, order_number, date_ordered
FROM store.store_orders_fact ord, public.vendor_dimension vd
WHERE ord.vendor_key = vd.vendor_key AND vd.deal_size IN
(SELECT MAX(deal_size) FROM public.vendor_dimension)
AND date_ordered = '2013-01-04';
store_key | order_number | date_ordered
-----------+--------------+--------------
166 | 36008 | 2013-01-04
113 | 66017 | 2013-01-04
198 | 75716 | 2013-01-04
27 | 150241 | 2013-01-04
148 | 182207 | 2013-01-04
9 | 188567 | 2013-01-04
45 | 202416 | 2013-01-04
24 | 250295 | 2013-01-04
121 | 251417 | 2013-01-04
(9 rows)