Come trovare le righe in una tabella che non hanno righe corrispondenti in un'altra tabella

StackOverflow https://stackoverflow.com/questions/1415438

  •  06-07-2019
  •  | 
  •  

Domanda

Ho una relazione 1: 1 tra due tabelle. Voglio trovare tutte le righe nella tabella A che non hanno una riga corrispondente nella tabella B. Uso questa query:

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

id è la chiave primaria in entrambe le tabelle. Oltre agli indici delle chiavi primarie, ho anche un indice sulla tabella A (id desc).

Utilizzando H2 (database incorporato Java), si ottiene una scansione completa della tabella B. Voglio evitare una scansione completa della tabella.

Come posso riscrivere questa query per eseguirla rapidamente? Quale indice dovrei?

È stato utile?

Soluzione

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

Se il tuo db sa come eseguire le intersezioni dell'indice, questo toccherà solo l'indice della chiave primaria

Altri suggerimenti

Puoi anche usare esiste , poiché a volte è più veloce di left join . Dovresti confrontarli con loro per capire quale vuoi usare.

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

Per mostrare che esiste può essere più efficiente di un left join , ecco i piani di esecuzione di queste query in SQL Server 2008:

left join - costo totale sottostruttura: 1.09724:

left join

existing - costo totale sottostruttura: 1.07421:

esiste

Devi controllare ogni ID nella tabella A con ogni ID nella tabella B. Un RDBMS completo (come Oracle) sarebbe in grado di ottimizzarlo in una SCANSIONE COMPLETA FAST INDICE e non toccare affatto la tabella. Non so se l'ottimizzatore di H2 sia così intelligente.

H2 supporta la sintassi MINUS, quindi dovresti provare questo

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

Che potrebbe funzionare più velocemente; vale senz'altro la valutazione comparativa.

Per il mio piccolo set di dati, Oracle fornisce a quasi tutte queste query lo stesso piano esatto che utilizza gli indici delle chiavi primarie senza toccare la tabella. L'eccezione è la versione MINUS che riesce a fare meno guadagni coerenti nonostante il costo del piano più elevato.

--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;

Non posso dirti quale di questi metodi sarà meglio su H2 (o anche se funzioneranno tutti), ma ho scritto un articolo che descrive in dettaglio tutti i (buoni) metodi disponibili in TSQL. Puoi dare loro una possibilità e vedere se qualcuno di loro funziona per te:

http://code.msdn.microsoft .com / SQLExamples / wiki / View.aspx title = QueryBasedUponAbsenceOfData & amp;? referringTitle = casa

select parentTable.id from parentTable
left outer join childTable on (parentTable.id = childTable.parentTableID) 
where childTable.id is null
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top