2011-01-21 13 views
10

Ho quello che sembra essere un problema semplice, ma non riesco a capire la soluzione corretta tramite SQL. Sto usando postgresql in particolare.Query SQL in cui TUTTI i record di un join corrispondono a una condizione?

adottare le seguenti:

SELECT * FROM users INNER JOIN tags ON (tags.user_id = users.id) WHERE tags.name IN ('word1', 'word2') 

Questo non fa quello che mi serve. Voglio trovare utenti i cui tag sono inclusi SOLO nell'elenco. Se l'utente ha un tag che non è nella lista, l'utente non dovrebbe essere incluso.

tag 'user1': word1, parola2, parola3
tag 'user2': word1
tag 'user3': word1, parola2

Data: parola1 e parola2. Voglio preparare una query che restituisce "utente2" e "utente3". 'utente1' è escluso perché ha un tag che non è nella lista.

Spero di averlo chiarito. Grazie per l'aiuto!

+2

possibile duplicato di [? SQL, come abbinare ALL] (http://stackoverflow.com/questions/4763143/sql-how-to-match -all) –

+0

Non hai appena chiesto questo –

+0

Gli utenti che non hanno alcun tag devono essere restituiti? – Quassnoi

risposta

6

Basandosi su COUNT (*) = 2, sarà necessario che non ci possono essere duplicati di user_id e nome nella tabella tag. Se è così, mi piacerebbe seguire questa strada. In caso contrario, questo dovrebbe funzionare:

SELECT u.* 
FROM users AS u 
WHERE u.id NOT IN (
    SELECT DISTINCT user_id FROM tags WHERE name NOT IN ('word1', 'word2') 
) AND EXISTS (SELECT user_id FROM tags WHERE user_id = u.id) 
+2

Questo * può * includere utenti senza tag. –

+0

@Andriy M: Hai ragione. Ho aggiornato la mia risposta per renderlo conto ora. Grazie per averlo precisato. – nybbler

+0

'DISTINCT' è solo un sovraccarico qui ... – JNK

1
SELECT user_id 
FROM users 
WHERE id IN 
     (
     SELECT user_id 
     FROM tags 
     ) 
     AND id NOT IN 
     (
     SELECT user_id 
     FROM tags 
     WHERE name NOT IN ('word1', 'word2') 
     ) 

o

SELECT u.* 
FROM (
     SELECT DISTINCT user_id 
     FROM tags 
     WHERE name IN ('word1', 'word2') 
     ) t 
JOIN users u 
ON  u.id = t.user_id 
     AND t.user_id NOT IN 
     (
     SELECT user_id 
     FROM tags 
     WHERE name NOT IN ('word1', 'word2') 
     ) 
+0

Ciò restituirà tutti gli utenti che corrispondono a entrambe le parole, senza verificare se non corrispondono ad altre parole. Questo non risponde alla domanda. – GolezTrol

+0

@GolezTrol: ha sbagliato il compito, grazie per aver indicato. – Quassnoi

0

Per ottenere tutti gli utenti che non dispongono di un tag che non è nella lista, utilizzare la query di seguito. Potrebbe essere che gli utenti vengono restituiti che non hanno tag o solo un tag corrispondente alle parole, ma capisco che è la funzionalità desiderata.

SELECT 
    u.* 
FROM 
    users u 
    LEFT JOIN tags t 
    ON t.user_id = u.userid AND 
     t.name NOT IN ('word1', 'word2') 
WHERE 
    t.user_id IS NULL 
0
SELECT u.* 
FROM users u 
INNER JOIN (
    SELECT user_id FROM tags WHERE name IN ('word1', 'word2') 
    EXCEPT 
    SELECT user_id FROM tags WHERE name NOT IN ('word1', 'word2') 
) s ON u.id = s.user_id 
0
SELECT distinct users.id 
FROM users 
INNER JOIN tags ON (tags.user_id = users.id) 
group by users.id 
having count(*) = 2 
and min(tags.name) = 'word1' 
and max(tags.name) = 'word2' 
+1

Potresti fornire qualche spiegazione sul perché la tua query è migliore di quella che è già stata pubblicata? – Theresa

Problemi correlati