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)

另请参阅