簡體   English   中英

在特殊情況下,SQL使用“左連接”替換“不進入”子句

[英]SQL using “Left Join” to replace “not in” clause in a special case

對於簡單的表,使用“ left join”和“ is null”替換“ Not In”應該很容易。 但是,就我而言,並不是那么簡單。

這是tableA(Item,ReferenceID)

Item(primary key)   ReferenceID
Chair                 123
Desk                  456
Sofa                  789
Bed                   111

這是tableB(StoreID,ReferenceID)

StoreID(primary key)    ReferenceID(primary key)    
00001                   123                         
00001                   456                         
00002                   123     
00002                   456     
00003                   111

注意:TableB是一個表,指示哪些商品在哪個商店中排除。 因此,storeID = 00001具有除Chair(ReferenceID = 123)和Desk(ReferenceID = 456)之外的所有項目。

給定一個StoreID = 00001 ,我如何編寫sql語句來實現此目的。 更具體地說,結果表應為:

Item(primary key)   ReferenceID
Sofa                  789
Bed                   111

使用“非插入”方法,該方法可以正常但緩慢地工作。

select * from tableA 
   where ReferenceID not in (select ReferenceID from tableB where storeID='00001'

現在,由於性能緩慢,我嘗試不使用“ not in”子句。 我嘗試使用“左聯接”,但它似乎沒有返回我想要的東西。

#1

select * from tableA left join tableB
   on tableA.referenceID = tableB.referenceID
 where tableB.StoreID is null

此方法將排除(bed,111),因為它存在於tableB中

#2。 嘗試添加storeID以過濾結果。

 select * from tableA left join tableB
         on (tableA.referenceID = tableB.referenceID and StoreID='00001')
 where tableB.StoreID is null 

結果集與#1中的方法相同,但不包括(bed,111)。

問題:

什么是達到此目的的正確SQL語句?

我也願意接受其他不使用“左連接”的方法,只要其性能優於使用“不插入”子句。

編輯:

我簡化了上面的實際SQL語句和情況,以使助手可以更輕松地理解我想要實現的目標,因為我認為跳過多余的表和SQL語句無關緊要。

根據下面的評論,我認為現在很重要,因為在上述簡化情況下,第二種方法似乎可以正常工作。 因此,我必須再添加一張表來重現我遇到的實際問題。

實際上,還有一張桌子。 我加入tableA和tableC,然后離開加入tableB。

tableC(item,itemDescrption)

  Item(primary key)   itemDescrption
    Chair                 Very comfortable.
    Desk                  broken
    sofa                  large sofa (24*12)
    bed                   double size

至於上述方法2,實際的陳述是

select * from tableA 
    inner join tableC on tableA.item = tableC.item 
    left join tableB
         on (tableA.referenceID = tableB.referenceID and StoreID='00001')
 where tableB.StoreID is null 

嘗試不存在。

SELECT * 
    FROM tableA tA
    WHERE NOT EXISTS(SELECT 1 
                         FROM tableB tB 
                         WHERE tB.ReferenceID = tA.ReferenceID
                             AND tB.storeID = '00001');

您必須將商品與商店cross join ,然后left join該結果。

select a.item,a.referenceID 
from tableA a
cross join (select distinct storeId from tableB) s
left join tableB b on b.referenceID=a.referenceID and b.storeId=s.storeId 
where s.storeId='00001' and b.referenceID is null

給定商店ID,這應該是您的查詢:

select a.* 
from tableA  A
INNER JOIN TableB B
    ON A.ReferenceID = B.ReferenceID
where A.storeID='00001'

我相信您的第二次嘗試是正確的方法(盡管,我認為NOT IN並沒有那么糟糕,但是如果這樣更快,那么我全力以赴):

mysql> SELECT * FROM tableA;
+-------+-------------+
| item  | ReferenceID |
+-------+-------------+
| Chair |         123 |
| Desk  |         456 |
| Sofa  |         789 |
| Bed   |         111 |
+-------+-------------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM tableB;
+---------+-------------+
| storeid | ReferenceID |
+---------+-------------+
| 1       |         123 |
| 1       |         456 |
| 2       |         123 |
| 2       |         456 |
| 3       |         111 |
+---------+-------------+
5 rows in set (0.00 sec)

mysql> select * from tableA left join tableB on (tableA.referenceID = tableB.referenceID and StoreID='1') where tableB.StoreID is null;
+------+-------------+---------+-------------+
| item | ReferenceID | storeid | ReferenceID |
+------+-------------+---------+-------------+
| Sofa |         789 | NULL    |        NULL |
| Bed  |         111 | NULL    |        NULL |
+------+-------------+---------+-------------+
2 rows in set (0.00 sec)

已針對tableC包含進行了更新(它對結果沒有影響,但仍可以按預期工作):

mysql> select * from tableA inner join tableC ON tableA.item = tableC.item left join tableB on (tableA.referenceID = tableB.referenceID and StoreID='1') where tableB.StoreID is null;
+------+-------------+------+--------------------+---------+-------------+
| item | ReferenceID | item | ReferenceID        | storeid | ReferenceID |
+------+-------------+------+--------------------+---------+-------------+
| Sofa |         789 | sofa | large sofa (24*12) | NULL    |        NULL |
| Bed  |         111 | bed  | double size        | NULL    |        NULL |
+------+-------------+------+--------------------+---------+-------------+
2 rows in set (0.00 sec)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM