如何使用NOT IN CLAUSE连接三个表

时间:2016-07-22 22:45:42

标签: sql sql-server left-join

场景......商店获得一个列表。 “LIST”基本上是需要计算的商店库存的SKU集合。

当商店开始计算分配给它的给定列表中的SKU时,该信息将保存在另一个名为“StoreCycles”的表中,该表记录了计数开始和完成的ListId,StoreName和Dates。

这些是我的表格。

表1.带有“Lists”的表,其主键为“ListId”

ListId ListName  
   1       abc
   2       def
   3       ghi

表2.“商店” - 上表(“列表”表)中的每个列表都分配给一个或多个商店。 “商店”表中的ListId是“列表”表格的主键。 Listid和LineId一起组成了外键。

ListId LineId StoreName
  1       1    StoreA
  1       2    StoreD
  2       1    StoreB
  2       2    StoreC
  2       3    StoreA
  3       1    StoreA

表3.'StoreCycles' - 在分配给商店的列表开始计数和完成时保存。

ListId  StoreName  StartDate   CompleteDate
  1      StoreA   2016-7-22    2016-7-22
  2      StoreA   2016-7-22
  2      StoreC   2016-7-22

我想在任何时候提取那些尚未完成的列表名称,即它们的完整日期为空。

这是我的疑问:

Select  T0.ListId,
T0.ListNaame  ,
T2.StartDate   
From    Lists T0
JOIN    Stores T1   On  T0.ListId  = T1.ListId 
LEFT JOIN StoreCycles T2   ON  T0.ListId  = T2.ListId
WHERE T1.StoreName = 'StoreA'
AND T0.ListId  NOT IN (SELECT ListId FROM StoreCycles WHERE CompleteDate IS NOT NULL)   

结果应该是>>

ListId ListName StartDate
  2      def      2016-7-22
  3      ghi      NULL

但我得到的结果就是这个

ListId ListName StartDate
 2      def        NULL
 2      def        NULL
 3      ghi        NULL

3 个答案:

答案 0 :(得分:1)

只是路过并转储SQL。

继续,没有什么可看的。

这里没有虫子狩猎。

declare @Lists table (ListId int primary key, ListName varchar(20));
insert into @lists values (1,'abc'),(2,'def'),(3,'ghi');

declare @Stores table (ListId int, LineId int, StoreName varchar(20));
insert into @Stores values 
(1,1,'StoreA'),
(1,2,'StoreD'),
(2,1,'StoreB'),
(2,2,'StoreC'),
(2,3,'StoreA'),
(3,1,'StoreA');

declare @StoreCycles table (ListId int, StoreName varchar(20), StartDate date, CompleteDate date);
insert into @StoreCycles values
(1,'StoreA','2016-7-22','2016-7-22'),
(2,'StoreA','2016-7-22',null),
(2,'StoreC','2016-7-22',null);

SELECT
L.ListId,
L.ListName,
SC.StartDate
FROM @Stores S   
JOIN @Lists L On (S.ListId  = L.ListId)
LEFT JOIN @StoreCycles SC ON (S.ListId  = SC.ListId AND S.StoreName = SC.StoreName)
WHERE S.StoreName = 'StoreA' 
AND SC.CompleteDate IS NULL;

答案 1 :(得分:0)

另一种看待它的方法是返回StartDate为NULL(无记录)或CompleteDate为NULL(不完整记录)的所有行。此外,如果外键使用2列,您可能希望在JOIN中使用这两列。

SELECT  T0.ListId,
        T0.ListName,
        T2.StartDate
FROM    Lists T0
            JOIN Stores T1   
                 ON T1.ListId = T0.ListId
            LEFT JOIN StoreCycles T2
                 ON T2.ListId = T1.ListId
                AND T2.LineId = T1.LineId
WHERE T1.StoreName = 'StoreA'
AND (T2.CompleteDate IS NULL OR T2.StartDate IS NULL)

答案 2 :(得分:0)

Select 
    l.ListId
    ,l.ListNaame 
    ,sc.StartDate
From
    Lists l
    JOIN Stores s
    ON  l.ListId  = s.ListId
    AND s.StoreName = 'StoreA' 
        LEFT JOIN StoreCycles sc 
        ON  s.ListId  = sc.ListId
        AND s.LineId = sc.LineId
WHERE
      sc.CompleteDate IS NULL

如果你正确构建它们,你已经在进行连接了,你的where子句中不需要select或not。此外,您与StoreCycles的关系似乎是错误的,因为您试图直接从Lists转到StoreCycles,但Stores是中间表。

还想到为什么不使用表别名来帮助你知道你所指的是什么表而不是t0,t1,t2,比如l,s,sc ....