Sql 左连接与不存在的位置
设置: 我有一个在线postgresql数据库实例的演示,其中包含虚拟公司Northwind的数据 为了在数据库实例中运行sql查询,请使用PgAdmin创建与数据库实例的连接,如下所示: db服务器的pwd为:XXtUvN2rDQpAxSsVweR_OK5DNBGTEYOU 连接设置完成后,请浏览数据库ikqhoff 数据库IKQHOFF具有以下图表: 任务: 哪些产品在1997年4月没有订单。 按asc中的productname订购 使用的解决方案1不存在,结果正确Sql 左连接与不存在的位置,sql,postgresql,Sql,Postgresql,设置: 我有一个在线postgresql数据库实例的演示,其中包含虚拟公司Northwind的数据 为了在数据库实例中运行sql查询,请使用PgAdmin创建与数据库实例的连接,如下所示: db服务器的pwd为:XXtUvN2rDQpAxSsVweR_OK5DNBGTEYOU 连接设置完成后,请浏览数据库ikqhoff 数据库IKQHOFF具有以下图表: 任务: 哪些产品在1997年4月没有订单。 按asc中的productname订购 使用的解决方案1不存在,结果正确 select
select
productname
from products as p
where not exists(
select productid
from order_details as od inner join orders using(orderid)
where od.productid = p.productid and
cast(orderdate as date) between cast('1997-04-01' as date) and cast('1997-04-30' as date)
)
order by productname asc;
select
distinct productname
from products left join order_details using(productid)
inner join orders using(orderid)
where cast(orderdate as date) not between cast('1997-04-01' as date) and cast('1997-04-30' as date)
order by productname asc;
解决方案2使用左连接,结果不正确
select
productname
from products as p
where not exists(
select productid
from order_details as od inner join orders using(orderid)
where od.productid = p.productid and
cast(orderdate as date) between cast('1997-04-01' as date) and cast('1997-04-30' as date)
)
order by productname asc;
select
distinct productname
from products left join order_details using(productid)
inner join orders using(orderid)
where cast(orderdate as date) not between cast('1997-04-01' as date) and cast('1997-04-30' as date)
order by productname asc;
问题
为什么解决方案2不能产生与解决方案1相同的结果,如何解决
预期结果
随着解决方案1的产生:
where子句将左连接转换为内部连接。我想你真的打算:
select distinct productname
from products p left join
order_details as od
using (productid) left join
orders as o
on o.orderid = od.orderid and
o.orderdate::date between '1997-04-01'::date and '1997-04-30'::date
where o.orderid is null
order by productname asc;
这将加入在该时间范围内有订单的所有产品。然后where子句过滤掉匹配的产品,使产品没有订单
我也不认为select distinct是必要的,只是给查询增加了不必要的开销。我的解决方案:
首先创建一个查询,显示1997-04年订单中的所有产品:
select distinct order_details.productid, products.productname
from order_details
inner join orders on orders.orderid=order_details.orderid
inner join products on order_details.productid=products.productid
where orders.orderdate between '1997-04-01' and '1997-04-30'
order by productid;
select p.productid, p.productname
from products p
left join (
select order_details.productid
from order_details
inner join orders on orders.orderid=order_details.orderid
inner join products on order_details.productid=products.productid
where orders.orderdate between '1997-04-01' and '1997-04-30'
) x on x.productid = p.productid
where x.productid is null
order by p.productid
;
然后选择所有产品,不包括1997-04年销售的产品:
select distinct order_details.productid, products.productname
from order_details
inner join orders on orders.orderid=order_details.orderid
inner join products on order_details.productid=products.productid
where orders.orderdate between '1997-04-01' and '1997-04-30'
order by productid;
select p.productid, p.productname
from products p
left join (
select order_details.productid
from order_details
inner join orders on orders.orderid=order_details.orderid
inner join products on order_details.productid=products.productid
where orders.orderdate between '1997-04-01' and '1997-04-30'
) x on x.productid = p.productid
where x.productid is null
order by p.productid
;
输出:
productid | productname
-----------+------------------------------
3 | Aniseed Syrup
5 | Chef Anton's Gumbo Mix
6 | Grandma's Boysenberry Spread
11 | Queso Cabrales
12 | Queso Manchego La Pastora
17 | Alice Mutton
19 | Teatime Chocolate Biscuits
22 | Gustaf's Knõckebr÷d
26 | Gumbõr Gummibõrchen
34 | Sasquatch Ale
36 | Inlagd Sill
37 | Gravad lax
50 | Valkoinen suklaa
51 | Manjimup Dried Apples
55 | PÔtÚ chinois
57 | Ravioli Angelo
58 | Escargots de Bourgogne
63 | Vegie-spread
64 | Wimmers gute Semmelkn÷del
71 | Flotemysost
73 | R÷d Kaviar
74 | Longlife Tofu
76 | Lakkalik÷÷ri
(23 rows)
嗨,戈登·林诺夫。我更新了我的问题。你能再看看这个问题吗?另外,我只对1997年4月没有订单的产品感兴趣。中按产品名称订购asc@HKN ... 这就是我对这个问题的解释以及这个问题的作用。下一票令人困惑。下一票是因为您提供的解决方案没有提供与解决方案1相同的结果。我确实觉得奇怪的是,您没有在sql中提到拼写错误。因为order\u id必须是orderid。如果你需要一个否决票,那么也请给出这样做的正当理由,不要含糊其辞,它没有做我想要它做的事do@Luuk否决票不是因为打字错误。在修复了我在此线程的编辑中所做的错误后,查询不会产生与解决方案1相同的结果。与共享数据库的连接详细信息相比,只共享DDL更安全。请共享一些有关“不匹配”结果的信息。这只是一个沙盒数据库。一旦这个问题得到解决,我将删除它。添加了有关预期结果的信息。如果您连接到SandboxDB并执行Solution2查询,您将看到它生成的结果与预期结果不匹配。非常感谢。它应该由p.productname订购,不按p.productid:从产品中选择p.productname p左连接选择订单\u详细信息。从订单\u详细信息中选择productid内部连接订单上的订单。orderid=订单\u详细信息。orderid内部连接订单上的产品\u详细信息。productid=products.productid,其中orders.orderdate介于“1997-04-01”和“1997-04-30”之间x上。productid=p、 productid,其中x.productid由p.productname指定为null order@香港邮政;;您是否注意到用户对提出的问题发表了评论,但没有提供解决方案或答案?解决问题是你的任务,通过对你的问题的评论可以使问题变得更容易。