【问题标题】:Using NOT EXISTS with a subquery对子查询使用 NOT EXISTS
【发布时间】:2020-12-27 23:57:06
【问题描述】:

我正在尝试创建一个查询来检索购买了一个 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')

【问题讨论】:

    标签: sql postgresql subquery not-exists


    【解决方案1】:

    您不需要子查询。
    您可以按客户分组并在having 子句中设置条件:

    SELECT o."FirstName", o."LastName", o."Email"
    FROM flight_export_order o INNER JOIN flight_export_orderline ol
    ON o."OrderDisplayID" = ol."OrderDisplayID"
    WHERE ol."SKU" IN ('Red399', 'Red323')
      AND o."OrderDate" BETWEEN '07/22/2020' AND '08/03/2020'
    GROUP BY o."FirstName", o."LastName", o."Email"
    HAVING SUM((ol."SKU" = 'Red399')::int) > 0
       AND SUM((ol."SKU" = 'Red323')::int) = 0
    

    【讨论】:

    • 谢谢,这行得通!只是为了澄清一下,以便我理解为什么会这样-您通过将 SKU 转换为 int 来获取购买的每瓶的数量,对吗?
    • 例如:布尔表达式 ol."SKU" = 'Red399' 被强制转换为 int:0 或 1 表示 false 和 true。因此,通过将这些 0 和 1 相加,如果您得到的数字 > 0,则购买了 'Red399'
    【解决方案2】:

    你一开始就走在正确的轨道上。 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'
       );
    

    使用flight_export_orderline ("OrderDisplayID", "SKU") 上的多列索引,这是最快的。仅在 ("OrderDisplayID")(就像您可能拥有的那样)上的索引也有很长的路要走。

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

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

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

    旁白 2:它是 reommended to use ISO 8601 date format (YYYY-MM-DD),它始终明确且独立于语言环境和会话设置。

    【讨论】:

    • 感谢您的解释!
    猜你喜欢
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 2019-01-12
    • 2010-12-08
    • 2016-07-22
    相关资源
    最近更新 更多