在子查询中使用 NOT EXISTS
Using NOT EXISTS with a subquery
我正在尝试创建一个查询来检索购买了一个 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')
您不需要子查询。
可以按客户分组,在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
您一开始就走在正确的轨道上。 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")
上的多列 index,这是最快的速度。仅 ("OrderDisplayID")
的索引(就像您可能拥有的那样)也有很长的路要走。
加上 flight_export_order("OrderDate")
上的索引,显然。
我认为不需要任何昂贵的聚合或 DISTINCT
。参见:
- Select rows which are not present in other table
旁白 1:如果可以,尽量避免在 Postgres 中使用带引号的 CaMeL-case 标识符。参见:
- Are PostgreSQL column names case-sensitive?
旁白 2:它是 reommended to use ISO 8601 date format (YYYY-MM-DD
),它始终明确且独立于语言环境和会话设置。
我正在尝试创建一个查询来检索购买了一个 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')
您不需要子查询。
可以按客户分组,在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
您一开始就走在正确的轨道上。 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")
上的多列 index,这是最快的速度。仅 ("OrderDisplayID")
的索引(就像您可能拥有的那样)也有很长的路要走。
加上 flight_export_order("OrderDate")
上的索引,显然。
我认为不需要任何昂贵的聚合或 DISTINCT
。参见:
- Select rows which are not present in other table
旁白 1:如果可以,尽量避免在 Postgres 中使用带引号的 CaMeL-case 标识符。参见:
- Are PostgreSQL column names case-sensitive?
旁白 2:它是 reommended to use ISO 8601 date format (YYYY-MM-DD
),它始终明确且独立于语言环境和会话设置。