簡體   English   中英

如何在一個表中查找在另一表中沒有對應行的行

[英]How to find rows in one table that have no corresponding row in another table

我在兩個表之間有 1:1 的關系。 我想找到表 A 中所有在表 B 中沒有對應行的行。我使用這個查詢:

SELECT id 
  FROM tableA 
 WHERE id NOT IN (SELECT id 
                    FROM tableB) 
ORDER BY id desc

id 是兩個表中的主鍵。 除了主鍵索引,我在 tableA(id desc) 上也有一個索引。

使用 H2(Java 嵌入式數據庫),這會導致對 tableB 進行全表掃描。 我想避免全表掃描。

如何重寫此查詢以快速運行? 我應該使用什么索引?

select tableA.id from tableA left outer join tableB on (tableA.id = tableB.id)
where tableB.id is null
order by tableA.id desc 

如果你的數據庫知道如何做索引交叉,這只會觸及主鍵索引

您也可以使用exists ,因為有時它比left join快。 您必須對它們進行基准測試才能確定要使用哪一個。

select
    id
from
    tableA a
where
    not exists
    (select 1 from tableB b where b.id = a.id)

為了表明existsleft join更有效,下面是SQL Server 2008 中這些查詢的執行計划:

left join - 總子樹成本:1.09724:

左連接

exists - 總子樹成本:1.07421:

存在

您必須根據 tableB 中的每個 ID 檢查 tableA 中的每個 ID。 功能齊全的 RDBMS(例如 Oracle)將能夠將其優化為 INDEX FULL FAST SCAN,並且根本不接觸表。 不知道H2的優化器有沒有這么聰明。

H2 確實支持 MINUS 語法,所以你應該試試這個

select id from tableA
minus
select id from tableB
order by id desc

那可能會執行得更快; 這當然值得進行基准測試。

對於我的小數據集,Oracle 為幾乎所有這些查詢提供了完全相同的計划,使用主鍵索引而不觸及表。 例外是 MINUS 版本,盡管計划成本較高,但它設法減少了一致的獲取。

--Create Sample Data.
d r o p table tableA;
d r o p table tableB;

create table tableA as (
   select rownum-1 ID, chr(rownum-1+70) bb, chr(rownum-1+100) cc 
      from dual connect by rownum<=4
);

create table tableB as (
   select rownum ID, chr(rownum+70) data1, chr(rownum+100) cc from dual
   UNION ALL
   select rownum+2 ID, chr(rownum+70) data1, chr(rownum+100) cc 
      from dual connect by rownum<=3
);

a l t e r table tableA Add Primary Key (ID);
a l t e r table tableB Add Primary Key (ID);

--View Tables.
select * from tableA;
select * from tableB;

--Find all rows in tableA that don't have a corresponding row in tableB.

--Method 1.
SELECT id FROM tableA WHERE id NOT IN (SELECT id FROM tableB) ORDER BY id DESC;

--Method 2.
SELECT tableA.id FROM tableA LEFT JOIN tableB ON (tableA.id = tableB.id)
WHERE tableB.id IS NULL ORDER BY tableA.id DESC;

--Method 3.
SELECT id FROM tableA a WHERE NOT EXISTS (SELECT 1 FROM tableB b WHERE b.id = a.id) 
   ORDER BY id DESC;

--Method 4.
SELECT id FROM tableA
MINUS
SELECT id FROM tableB ORDER BY id DESC;

我不能告訴你這些方法中的哪一個最適合 H2(或者即使它們都可以工作),但我確實寫了一篇文章詳細介紹了 TSQL 中可用的所有(好的)方法。 您可以試一試,看看它們是否適合您:

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=QueryBasedUponAbsenceOfData&referringTitle=Home

select parentTable.id from parentTable
left outer join childTable on (parentTable.id = childTable.parentTableID) 
where childTable.id is null

暫無
暫無

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

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