我一直在练习SQL基本查询,但我坚持在一个任务。我的意思是-我知道如何做,但当我尝试应用反向逻辑,似乎有些错误,我不明白是什么使其他查询产生错误的结果。所以任务如下:“列出购买了自行车但未购买 Helm 的客户。”因此,通过“不存在”解决此问题非常简单:
SELECT DISTINCT(o.customerid)
FROM salesordersexample.order_details od
JOIN salesordersexample.products p ON od.productnumber = p.productnumber
JOIN salesordersexample.categories c ON c.categoryid = p.categoryid
JOIN salesordersexample.orders o ON od.ordernumber = o.ordernumber
WHERE NOT EXISTS
(
SELECT DISTINCT(o2.customerid)
FROM salesordersexample.order_details od2
JOIN salesordersexample.products p2 ON od2.productnumber = p2.productnumber
JOIN salesordersexample.categories c2 ON c2.categoryid = p2.categoryid
JOIN salesordersexample.orders o2 ON od2.ordernumber = o2.ordernumber
WHERE p2.productname LIKE '%Helmet%' AND o.customerid = o2.customerid
)
AND p.productname ILIKE '%bike%';
但是当我想使用EXISTS时,我认为在子查询中将LIKE转换为NOT LIKE就足够了,我的逻辑强烈地引导我实现这个想法。我试图理解正在发生的事情,但我没有任何线索。无法正常工作查询:
SELECT DISTINCT(o.customerid)
FROM salesordersexample.order_details od
JOIN salesordersexample.products p ON od.productnumber = p.productnumber
JOIN salesordersexample.categories c ON c.categoryid = p.categoryid
JOIN salesordersexample.orders o ON od.ordernumber = o.ordernumber
WHERE EXISTS
(
SELECT DISTINCT(o2.customerid)
FROM salesordersexample.order_details od2
JOIN salesordersexample.products p2 ON od2.productnumber = p2.productnumber
JOIN salesordersexample.categories c2 ON c2.categoryid = p2.categoryid
JOIN salesordersexample.orders o2 ON od2.ordernumber = o2.ordernumber
WHERE p2.productname NOT LIKE '%Helmet%' AND o.customerid = o2.customerid
)
AND p.productname ILIKE '%bike%';
第一个查询返回了正确的结果- 2行,而第二个查询是错误的,返回了27行。我深信问题是微不足道的,但我不明白为什么结果是错误的。
1条答案
按热度按时间bq3bfh9z1#
这两个子查询在逻辑上并不等效。
在第一个查询中,
not exists
子查询确保客户没有购买 Helm -这正是您想要的。在第二个查询中,
exists
检查他们是否至少购买了不是 Helm 的东西--不管他们是否购买了 Helm 。但是,由于查询的其余部分确保他们确实已经购买了自行车,因此子查询总是查找匹配的行简单地说,exists
条件不过滤任何行,查询只返回所有购买自行车的客户。注:
(not) exists
检查是否有匹配的行,因此select distinct
是多余的:select 1
就足够了,数据库可能会在幕后为您进行优化,但是显式是更好的做法,可以使查询更容易执行group by
来描述逻辑,用having
子句来过滤,这样就不需要在子查询中重复连接