首页 > 解决方案 > 对子查询使用 NOT EXISTS

问题描述

我正在尝试创建一个查询来检索购买了一个 SKU('Red399')但没有购买第二个 SKU('Red323')的所有客户。似乎最好的方法是使用NOT EXISTS子查询来过滤掉购买“Red323”的人。

我的查询没有返回任何错误,但也没有返回任何结果,我认为这可能是因为我在初始子句中有太多条件WHERE但我不确定:

SELECT DISTINCT o."FirstName", o."LastName", o."Email", ol."SKU"
FROM flight_export_order o
JOIN flight_export_orderline ol
    ON o."OrderDisplayID" = ol."OrderDisplayID"
WHERE ol."SKU" = 'Red399'
AND o."OrderDate" BETWEEN '07/22/2020' AND '08/03/2020'
AND NOT EXISTS 
(SELECT DISTINCT o."Email" 
    FROM flight_export_order o
    JOIN flight_export_orderline ol
        ON o."OrderDisplayID" = ol."OrderDisplayID"
    WHERE ol."SKU" = 'Red323'
    AND o."OrderDate" BETWEEN '07/22/2020' AND '08/03/2020')

标签: sqlpostgresqlsubquerynot-exists

解决方案


你一开始就走在正确的轨道上。EXISTS/NOT EXISTS是正确的工具:

SELECT o.* --  or just the columns you need
FROM   flight_export_order o
WHERE  o."OrderDate" BETWEEN '2020-07-22' AND '2020-08-03'
AND    EXISTS (
   SELECT FROM flight_export_orderline
   WHERE  "OrderDisplayID" = o."OrderDisplayID"
   AND    "SKU" = 'Red399'
   )
AND    NOT EXISTS (
   SELECT FROM flight_export_orderline
   WHERE  "OrderDisplayID" = o."OrderDisplayID"
   AND    "SKU" = 'Red323'
   );

使用多列索引on flight_export_orderline ("OrderDisplayID", "SKU"),这是尽可能快的。一个关于just(就像你可能有)的索引("OrderDisplayID")也有很长的路要走。

flight_export_order("OrderDate")显然,加上一个索引。

我认为不需要任何昂贵的聚合或DISTINCT. 看:

除了 1:如果可以的话,尽量避免在 Postgres 中引用 CaMeL-case 标识符。看:

旁白2:建议使用 ISO 8601 日期格式( YYYY-MM-DD),它始终明确且独立于语言环境和会话设置。


推荐阅读