SQL Not IN和Not Exists子句不适用于Where条件

时间:2019-09-28 09:57:10

标签: sql sql-server

我正在尝试获取在给定日期之前售出的商品以及从未售出的商品。
因此,使用以下查询,我得到在给定日期之前已售出的物品,但我没有得到从未售出的物品。

当我分别执行NOT INNOT EXIST查询时,我得到ItemsSold表中不存在的项目。怎么了

不存在的完整查询

select MAx(ITM.Name) as Name,Max(ITM.ItemID) as ID,Max(ItemsSold.UpdatedDate) as LastSaleDate from Items ITM
Inner join ItemsSold on ItemsSold.ItemID = ITM.ItemID
where convert(varchar,ItemsSold.UpdatedDate,111) < '2019/04/01'
or  NOT EXISTS (select ItemsSold.ItemID from ItemsSold where ItemsSold.ItemID=ITM.ItemID) 
Group by ITM.ItemID order by ITM.ItemID;  

使用NOT IN的完整查询

select MAx(ITM.Name) as Name,Max(ITM.ItemID) as ID,Max(ItemsSold.UpdatedDate) as LastSaleDate from Items ITM
Inner join ItemsSold on ItemsSold.ItemID = ITM.ItemID
where convert(varchar,ItemsSold.UpdatedDate,111) < '2019/04/01'
or ITM.ItemID NOT IN (select ItemsSold.ItemID from ItemsSold) 
Group by ITM.ItemID order by ITM.ItemID  

不能单独进入

select Items.Name,Items.ItemID from Items where Items.ItemID NOT IN (select ItemsSold.ItemID from ItemsSold) order by ItemID  

分别执行NOT IN和NOT EXISTS查询不会返回实际正确的数据,但是对于完整查询则不会。

2 个答案:

答案 0 :(得分:2)

没有示例数据或预期结果,这仅仅是一个猜测,仅基于您现有的SQL和您的注释“否!我想要一个在给定日期之前售出的商品清单以及从未出售。” 这可能是您想要的:

SELECT I.ItemID
FROM Items I
     LEFT JOIN ItemsSold ItS ON I.ItemID = ItS.ItemID
GROUP BY I.ItemID
HAVING MAX(ItS.UpdatedDate) < '20190401' --Proper date logic, got rid of CONVERT
    OR MAX(ItS.ItemID) IS NULL;

您可能想要MIN(ItS.UpdatedDate),具体取决于您是否想在2019-04-01之前出售仅 的商品,还是想要至少首先出售的商品< strong>之前 2019-04-01(由于缺乏描述而无法知道)。

如果没有,请参考我以前的评论“我们在这里需要复制“问题”和预期结果的示例数据。”

答案 1 :(得分:1)

您似乎想要在特定日期之前仅售出 或从未售出的物品。也就是说,以后没有出售任何物品:

使用not exists

select i.*
from items i
where not exists (select 1
                  from itemssold its
                  where its.ItemId = i.ItemId and
                        its.UpdatedDate >= '2019-04-01'
                 );

如果考虑性能,无论您如何用词组查询,都需要适当的索引。为此,索引应位于itemssold(ItemId, UpdatedDate)上。这应该比查询的聚合形式快得多。

如果问题更多是措辞:日期之前存在一个订单,或者根本没有订单,那么您将使用两个比较:

select i.*
from items i
where exists (select 1
              from itemssold its
              where its.ItemId = i.ItemId and
                    its.UpdatedDate < '2019-04-01'
             ) or
      not exists (select 1
                  from itemssold its
                  where its.ItemId = i.ItemId
                 );
相关问题