2012-05-16 29 views
6

ho questa tabella:Strano comportamento con NOT IN

select count(distinct clean_deep_link) from tbl_1; 
+---------------------------------+ 
| count(distinct clean_deep_link) | 
+---------------------------------+ 
|       121211 | 
+---------------------------------+ 

ho questa query:

select count(1) from tbl_1 where clean_deep_link IN 
    (select clean_deep_link from tbl_2); 

+----------+ 
| count(1) | 
+----------+ 
| 66360 | 
+----------+ 

Ma quando cambio la query per not in restituisce un insieme vuoto:

select count(1) from tbl_1 
where clean_deep_link not in (select clean_deep_link from tbl_2); 
+----------+ 
| count(1) | 
+----------+ 
|  0 | 
+----------+ 

Com'è possibile? se la sottoquery contiene circa la metà dei record, la not della sottoquery non dovrebbe contenere l'altra metà? Cosa mi manca qui?

Grazie

+0

Prova 'SELECT count (*), count (1) DA tbl_1 ...' – vyegorov

+0

Avete nulli nella colonna? Cosa significa 'SELECT COUNT (*) FROM tbl_1 WHERE clean_deep_link IS NULL? Return? –

+2

In altre parole, ci sono tre metà in una tabella SQL. –

risposta

9

presumo che tbl_1.clean_deep_link è NULL per il resto delle righe.

Questi valori non sono né INNOT IN sotto-query.


L'altro motivo potrebbe essere, di avere NULL in tbl_2.clean_deep_link.

prova le seguenti:

select count(1) from tbl_1 
where clean_deep_link not in (select clean_deep_link 
           from tbl_2 WHERE clean_deep_link IS NOT NULL); 

Il problema con NULL è che non è né =, nè <> qualsiasi altro valore (compreso NULL).

Controllando per NOT IN, MySQL deve controllare per ogni valore in tbl_1 che non è contenuto in tbl_2 e quindi verifica se sono <>.

I suoi valori erano non<> NULL, quindi erano nonNOT IN.

Consulta anche: Using NOT IN operator with null values


check esempio in SQL Fiddle.

+0

che era il tbl_1 ... – WeaselFox

+0

Sì, c'era un singolo record in tbl_2 che aveva NULL per clean_deep_link ... quando avevo rimosso quel record, la sottoquery funzionava bene. Come potrebbe averlo causato? – WeaselFox

+0

Ho cercato di spiegarlo nel mio recente aggiornamento, spero che non sia troppo confuso;) Considera di mettere un vincolo 'NOT NULL' su' tbl_2.clean_deep_link' per evitare questo problema. –

2

Le colonne NULL in MySQL vengono conteggiate come distinte, quindi tre valori NULL sono tutti considerati distinti.

Come accennato altrove, non è possibile confrontare NULL con altri valori utilizzando operatori di confronto convenzionali, tra cui IN e NOT IN.

I seguenti operatori in grado di gestire NULL valori

0
SELECT COUNT(*) - COUNT(1) 
FROM tbl_1 
WHERE clean_deep_link IN (
    SELECT clean_deep_link 
    FROM tbl_2 
);