2013-11-30 6 views
1

Предположим, у меня есть две таблицы SQL. Тот, который представляет сообщение с столбцами (post_id, post_content) и тот, который представляет теги, связанные с сообщением с столбцами (post_id, tag_text).SQL select и внутреннее соединение с AND

Что я должен делать, если я хочу, чтобы получить должность, которые имеют TAG1 и TAG2, так как запрос, как

SELECT post_id FROM posts JOIN tags ON posts.post_id=tags.post_id 
WHERE tag_text ='TAG1' AND tag_text='TAG2' 

явно не делать то, что я хочу?

EDIT: Обратите внимание, что число И динамически генерируется в моих примерах. То есть, недостаточно удвоить внутреннее соединение.

+0

Для пояснения, если у вас есть, например, 3 сообщения, один с "TAG1", второй с "TAG1" и "tag2", а третий с "TAG1", "tag2" и «TAG3 «Я исправлю, что только второй и третий будут подняты (используя критерии в вашем примере)? –

ответ

0

Вот запрос:

SELECT * FROM posts p 
WHERE 
EXISTS (SELECT 1 FROM tags t1 WHERE t1.post_id = p.post_id AND t1.tag_text='TAG1') 
AND 
EXISTS (SELECT 1 FROM tags t2 WHERE t2.post_id = p.post_id AND t2.tag_text='TAG2') 

Вы можете создать динамический запрос (Dynamic СУЩЕСТВУЕТ для каждого тега), если количество текстов тегов не зафиксировано.

+0

Решение, предоставленное @jpw, тоже правильно, но я считаю, что мое решение лучше для производительности, потому что я использую EXISTS здесь. – Loc

+2

При условии правильных индексов и отношений внешнего ключа запросы, скорее всего, сгенерируют идентичные планы выполнения (по крайней мере, в SQL Server), поэтому я думаю, что это вопрос предпочтения :) Ответ, предоставленный @a_horse_with_no_name, должен превзойти оба наших ответа, хотя , – jpw

0
select p.post_id 
from posts p 
    join tags t ON p.post_id=t.post_id 
where t.tag_text in ('TAG1', 'TAG2') 
group by p.post_id 
having count(distinct t.tag_text) = 2; 

Это, однако, также возвращать сообщения, которые имеют больше, чем те два тега (например, tag1, tag2 и Tag3). Если вы не хотите, что вам нужно, чтобы ограничить результат тех должностей, которые имеют ровно две метки:

select p.post_id 
from posts p 
    join tags t ON p.post_id=t.post_id 
where t.tag_text in ('TAG1', 'TAG2') 
group by p.post_id 
having count(distinct t.tag_text) = 2 
    and count(distinct t.tag_text) = (select count(*) 
            from tags t2 
            where t2.post_id = t.post_id); 

Btw: если вы только хотите post_id вам не нужно объединение вообще:

select post_id 
from tags 
where tag_text in ('TAG1', 'TAG2') 
group by post_id 
having count(distinct tag_text) = 2; 
Смежные вопросы