Sql 左连接与不存在的位置

Sql 左连接与不存在的位置,sql,postgresql,Sql,Postgresql,设置: 我有一个在线postgresql数据库实例的演示,其中包含虚拟公司Northwind的数据 为了在数据库实例中运行sql查询,请使用PgAdmin创建与数据库实例的连接,如下所示: db服务器的pwd为:XXtUvN2rDQpAxSsVweR_OK5DNBGTEYOU 连接设置完成后,请浏览数据库ikqhoff 数据库IKQHOFF具有以下图表: 任务: 哪些产品在1997年4月没有订单。 按asc中的productname订购 使用的解决方案1不存在,结果正确 select

设置: 我有一个在线postgresql数据库实例的演示,其中包含虚拟公司Northwind的数据

为了在数据库实例中运行sql查询,请使用PgAdmin创建与数据库实例的连接,如下所示:

db服务器的pwd为:XXtUvN2rDQpAxSsVweR_OK5DNBGTEYOU

连接设置完成后,请浏览数据库ikqhoff

数据库IKQHOFF具有以下图表:

任务:

哪些产品在1997年4月没有订单。 按asc中的productname订购

使用的解决方案1不存在,结果正确

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@香港邮政;;您是否注意到用户对提出的问题发表了评论,但没有提供解决方案或答案?解决问题是你的任务,通过对你的问题的评论可以使问题变得更容易。