Mysql 使用无子查询重写包含两个子查询的查询

Mysql 使用无子查询重写包含两个子查询的查询,mysql,sql,Mysql,Sql,给定数据库架构: Part( PID, PName, Producer, Year, Price) Customer( CID, CName, Province) Supply(SID, PID, CID, Quantity, Amount, Date) 以及查询: Select cname, Province From Customer c Where exists ( Select * from Supply s join Part p on p.pId = s.

给定数据库架构:

Part( PID, PName, Producer, Year, Price)
Customer( CID, CName, Province)
Supply(SID, PID, CID, Quantity, Amount, Date)
以及查询:

Select cname, Province
From Customer c
Where exists (
    Select * 
    from Supply s
    join Part p on p.pId = s.pId 
    Where CId = c.CId 
    and p.Producer = 'Apple'
)
and Not exists (
    Select * 
    from Supply n
    join Part nap on nap.pId = n.pId 
    Where CId = c.CId 
    and nap.Producer != 'Apple'
)

如果没有这两个子查询,我将如何重写这个查询

您想要只购买苹果产品的客户吗

一种可能的解决方案基于条件聚合:

Select c.cname, c.Province
From Customer c
join
 ( -- this is not a Subquery, it's a Derived Table
   Select s.CId -- assuming there's a CId in Supply
   from Supply s
   join Part p
     on p.pId = s.pId
   group by s.CId 
   -- when there's any other supplier this will return 1
   having max(case when p.Producer = 'Apple' then 0 else 1 end) = 0
 ) as p
on p.CId = c.CId 

您可以使用
LEFT JOIN/NULL
模式查找尚未购买任何非苹果产品的客户。然后你就可以用连接来完成这一切。您必须加入
供应
零件
两次,一次用于查找苹果产品,另一次用于排除非苹果产品

SELECT distinct c.name, c.province
FROM Customer AS c
JOIN Supply AS s1 ON s1.cid = c.cid
JOIN Parts AS p1 ON p1.pid = s1.pid
LEFT JOIN Supply AS s2 ON s2.cid = c.cid
LEFT JOIN Parts AS p2 ON p2.pid = s2.pid AND p2.producer != 'Apple'
WHERE p1.producer = 'Apple' AND p2.pid IS NULL

注意,在
LEFT JOIN
中,您将第二个表的限制放在
ON
子句中,而不是
WHERE
子句中。有关此部分查询的更多信息,请参阅。

我觉得您的查询很好。你为什么要重写它?