2011-01-21 11 views
10

私は単純な問題と思われるものを持っていますが、SQL経由で適切な解決策を理解することはできません。私は特にpostgresqlを使用しています。ジョイン内のすべてのレコードが条件と一致するSQLクエリ?

次してください:

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

これは私が必要なものを行いません。タグがリストにのみ含まれているユーザーを探したい。ユーザーがリストにないタグを持っている場合は、ユーザーを含めてはいけません。

'USER1' タグ:WORD1、WORD2は、
'user2の' タグをWORD3:単語1
'がUSER3' タグ:単語1とWORD2:単語1を、与えられた

をWORD2。私は 'user2'と 'user3'を返すクエリを用意したいと思います。 'user1'はタグがリストにないため除外されます。

私はこれを明確にしました。ご協力いただきありがとうございます!

+2

可能重複[?SQL、一致させるためにどのようにALL](http://stackoverflow.com/questions/4763143/sql-how-to-match -all) –

+0

これは尋ねられませんでした –

+0

タグのないユーザーは返されますか? – Quassnoi

答えて

6

COUNT(*)= 2にすると、タグテーブルにuser_idとnameの重複がないことが必要になります。その場合、私はその道を行くだろう。そうでない場合は、この作業をする必要があります:

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

これは*タグなしのユーザーを含むかもしれません。 –

+0

@Andriy M:あなたは正しいです。私は今これについて説明するために私の答えを更新しました。それを指摘していただきありがとうございます。 – nybbler

+0

'DISTINCT'はちょうど余分なオーバーヘッドです... – 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') 
     ) 

または

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

これは、両方の単語に一致するすべてのユーザーが、他の単語と一致しないかどうかを確認せずに、すべてのユーザーを返します。これは質問に答えません。 – GolezTrol

+0

@GolezTrol:タスクを間違っている、指してくれてありがとう。 – Quassnoi

0

以下のクエリを使用して、リストにないタグを持たないすべてのユーザーを取得します。タグがない、または単語に一致するタグが1つしかないユーザーが返される可能性がありますが、それが望ましい機能であると私は理解しています。

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

あなたのクエリが既に投稿されているものより優れている理由についていくつかの説明を教えてください。 – Theresa

関連する問題