[英]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)
為了表明exists
比left 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 中可用的所有(好的)方法。 您可以試一試,看看它們是否適合您:
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.