sql >> Database teknologi >  >> RDS >> PostgreSQL

PostgreSQL:Hvordan finder man ud af manglende tal i en kolonne ved hjælp af gener_series()?

Givet eksempeldata:

create table results ( commandid integer primary key);
insert into results (commandid) select * from generate_series(1,1000);
delete from results where random() < 0.20;

Dette virker:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE NOT EXISTS (SELECT 1 FROM results WHERE commandid = s.i);

ligesom denne alternative formulering:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
LEFT OUTER JOIN results ON (results.commandid = s.i) 
WHERE results.commandid IS NULL;

Begge ovenstående ser ud til at resultere i identiske forespørgselsplaner i mine tests, men du bør sammenligne med dine data på din database ved hjælp af EXPLAIN ANALYZE for at se, hvilken der er bedst.

Forklaring

Bemærk, at i stedet for NOT IN Jeg har brugt EKSISTERER IKKE med en underforespørgsel i én formulering og en almindelig OUTER JOIN i den anden. Det er meget nemmere for DB-serveren at optimere disse, og det undgår de forvirrende problemer, der kan opstå med NULL s i NOT IN .

Jeg foretrak oprindeligt OUTER JOIN formulering, men i det mindste i 9.1 med mine testdata EKSISTERER IKKE form optimerer til den samme plan.

Begge vil fungere bedre end NOT IN formulering nedenfor, når serien er stor, som i dit tilfælde. IKKE IN bruges til at kræve, at Pg laver en lineær søgning i IN liste for hver tuple, der testes, men undersøgelse af forespørgselsplanen tyder på, at Pg kan være smart nok til at hash det nu. FINDER IKKE (omdannet til en JOIN af forespørgselsplanlæggeren) og JOIN arbejde bedre.

NOT IN formulering er både forvirrende i nærvær af NULL commandid s og kan være ineffektiv:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE s.i NOT IN (SELECT commandid FROM results);

så jeg ville undgå det. Med 1.000.000 rækker fuldførte de to andre på 1,2 sekunder og NOT IN formulering kørte CPU-bundet, indtil jeg kedede mig og annullerede den.



  1. Få postgresql-array til struct med StructScan

  2. BESTIL AF med indre forespørgsel, hvilket giver ORA-00907 manglende højre parentes

  3. forbinder Python 2.6.1 med MySQLdb

  4. gruppering af hver N-værdi