2012-04-04 12 views
20

query: select id from users where id in (1,2,3,4,5)SELECT che restituisce una lista di valori non si verificano in qualsiasi riga

Se la tabella degli utenti contiene gli ID 1, 2, 3, questo sarebbe di ritorno 1, 2, e 3. voglio una query che sarebbe tornato 4 e 5. In altre parole, non voglio che la query restituisca tutte le righe esistenti nella tabella, voglio dargli un elenco di numeri e ottenere i valori da quella lista che non appaiono nel tavolo.

(aggiornato per chiarire domanda seguente più risposte inapplicabili)

+0

Come si scegliere i id per 1,2 , 3,4,5? è un numero fisso o da 1 a max ID usato? – BugFinder

+0

@BugFinder: che sono numeri fissi. – Dev

+0

Mi manca qualcosa qui? La tua tabella utenti contiene solo ID 1,2 e 3, ma vuoi ottenere 4 e 5 di id? Dove sono id 4 e 5? Se non sono nella tabella degli utenti, non otterrai nulla se dici 'seleziona id dagli utenti dove id in (4,5)' o qualunque altra query tu lanci su di esso ... – DaveyBoy

risposta

10

Dati i numeri sono un elenco fisso. Il modo più rapido a cui riesco a pensare è di avere una tabella di test, popolata con quei numeri e fare

affermazione select non testata - ma seguirai il princpal.

select test.number from test left join users on test.number = users.id where test.number<>users.id 

Poi si otterrà indietro tutti i numeri che non hanno un user.id di corrispondenza e così può riempire i buchi ..

+1

risposta da @safarov .... 'ID SELECT FROM temp_ids WHERE temp_ids.id NOT IN (ID SELECT FROM utenti)' sembra anche bene. – Dev

+0

@BugFinder +1, finalmente ottieni la domanda – safarov

+0

Questa è una buona idea. Ha il benefico effetto collaterale che l'intervallo di possibili ID è memorizzato in una tabella, piuttosto che essere nascosto in una query da qualche parte nel codice. – octern

1

Scrivi not in invece di in

select id from users where id not in (1,2,3,4,5) 

Se si vuole il contrario nella lista, ma non nella tabella. Temp_ids è tabella temporanea consiste della vostra lista id

SELECT id FROM temp_ids WHERE temp_ids.id NOT IN (SELECT id FROM users) 
+0

-1, Non corretto, questo non restituirà alcun risultato, ma ho bisogno di 4 e 5. dove ci sono nella lista ma non nella colonna id della tabella utenti. La tabella – Dev

+0

contiene 3 record con ID: 1,2,3 – Dev

+0

Il problema è dev sta cercando di trovare i numeri mancanti da un elenco, quindi se l'intervallo era da 1 a 5 o da 1 a 1000, hes dopo un elenco di numeri disponibili dall'intervallo che non sono stati assegnati – BugFinder

2

Una diversa opzione è quella di utilizzare un'altra tabella che contiene tutte le possibili ids e poi fare una selezione da lì:

mysql> describe ids; 
+-------+-----------------+------+-----+---------+-------+ 
| Field | Type   | Null | Key | Default | Extra | 
+-------+-----------------+------+-----+---------+-------+ 
| id | int(5) unsigned | NO |  | 0  |  | 
+-------+-----------------+------+-----+---------+-------+ 
1 row in set (0.05 sec) 

mysql> select * from ids; 
+----+ 
| id | 
+----+ 
| 1 | 
| 2 | 
| 3 | 
| 4 | 
| 5 | 
+----+ 
5 rows in set (0.00 sec) 

mysql> select * from users; 
+----+ 
| id | 
+----+ 
| 1 | 
| 2 | 
| 3 | 
+----+ 
3 rows in set (0.00 sec) 


mysql> select id from ids where id not in (select id from users); 
+----+ 
| id | 
+----+ 
| 4 | 
| 5 | 
+----+ 
2 rows in set (0.04 sec) 

Aggiunto effetto collaterale - consente di espandere l'elenco dei risultati inserendo nella tabella ids

+0

Sì, quello era il mio suggerimento. – BugFinder

+0

@BugFinder - scusate - Sono un po 'lento con l'assorbimento oggi – DaveyBoy

+1

Questo è OK il vostro ha avuto belle foto :) – BugFinder

10

avuto la stessa esigenza e costruito sulla risposta da BugFinder utilizzando una tabella temporanea in sessione. In questo modo verrà automaticamente distrutto dopo aver terminato la query, quindi non devo occuparmi della pulizia della casa poiché eseguirò spesso questo tipo di query.

Creare la tabella temporanea:

CREATE TEMPORARY TABLE tmp_table (id INT UNSIGNED); 

Popola tmp_table con i valori che si verifica:

INSERT INTO tmp_table (id) values (1),(2),(3),(4),(5); 

Con la tabella creata e popolata, eseguire la query come con qualsiasi tavolo regolare:

SELECT tmp_table.id 
    FROM tmp_table 
    LEFT JOIN users u 
    ON tmp_table.id = u.id 
    WHERE u.id IS NULL; 

This info on MySQL Temporary Tables was also useful

13

Se non si desidera (esplicitamente) utilizzare le tabelle temporanee, questo funziona:

SELECT id FROM (
    (SELECT 1 AS id) UNION ALL 
    (SELECT 2 AS id) UNION ALL 
    (SELECT 3 AS id) UNION ALL 
    (SELECT 4 AS id) UNION ALL 
    (SELECT 5 AS id) 
) AS list 
LEFT JOIN users USING (id) 
WHERE users.id IS NULL 

Tuttavia, è abbastanza brutto, piuttosto lungo, e io sono dubbioso sul come sarebbe eseguire se la lista di ID è lungo.

+0

Grazie, solo per completezza. Se i numeri sono un VARCHAR devi assicurarti di usare lo stesso tipo di CHARACTER altrimenti ottieni un ERRORE 1267 SO se il tuo DataBade è utf8 -> ID SELECT FROM ( (SELEZIONA CONVERT ("1" UTILIZZANDO UTf8) AS id) UNION ALL (SELEZIONA CONVERT ("2" USANDO utf8) AS id) UNION ALL (SELEZIONA CONVERT ("3" USANDO utf8) AS id) UNION ALL (SELEZIONA CONVERT ("4" USANDO utf8) AS id) UNION ALL (SELEZIONA CONVERTITO ("5" UTILIZZANDO UTf8) AS id) ) AS lista LEFT JOIN utenti USING (id) WHERE users.id È NULL; MI spiace so che Duro leggere in un commento = ^) – irJvV

0

Mi dispiace, non posso aggiungere commenti, @Austin,

Hai la mia +1.

In ogni caso, non so se questo funziona su mysql, ma cambiare tutti che seleziona atomiche sindacati concatenati per un set di valore, in modo da avere qualcosa di simile:

SELECT id FROM (
    VALUES (1), (2), (3), (4), (5) 
) AS list(id) 
LEFT JOIN users USING (id) 
WHERE users.id IS NULL 
Problemi correlati