Pergunta

Dada uma tabela de itens, uma tabela de tags e uma tabela de junção entre eles, o que é um bom e eficiente maneira de implementar consultas da forma:

p1 AND p2 AND ... AND pn AND NOT n1 AND NOT n2 ... AND NOT nk

Eu estou usando SQL. Então, para encontrar todos os itens que correspondem todas as tags p1 ... pn e nenhuma das n1 ... nk?

Existe uma boa solução "standard" para isso?

Foi útil?

Solução

É difícil dizer sem saber seu esquema, mas algo como isso iria funcionar:

select article_id from articles
inner join tag t1 on t1.article_id=articles.article_id and t1.tag='included_tag'
inner join tag t2 on t2.article_id=articles.article_id and t2.tag='another_included_tag'
left outer join tag t3 on t3.article_id=articles.article_id and t3.tag='dont_include_tag'
left outer join tag t4 on t4.article_id=articles.article_id and t4.tag='also_dont_include_tag'
where t3.tag_id is null and t4.tag_id is null

junção interna para as etiquetas que são para ser incluídos, e fazer aderir um anti-(+ junção externa onde uma coluna necessária é nulo) para as etiquetas que não são para ser incluídos

Outras dicas

Eu acho que isso é o que você está procurando:

SELECT * FROM TABLE_NAME WHERE COLUMN1 IN ('value1','value2','value3') AND COLUMN1 NOT IN ('value4','value5','value6')

Se não, deixe-me saber. Talvez eu tenha entendido mal a sua pergunta.

Depende de como você está armazenando as tags no banco de dados, mas você provavelmente vai querer o operador IN:

SELECT tag FROM myTags WHERE tag IN ('p1','p2',...)
SELECT tag FROM myTags WHERE tag NOT IN ('p1','p2',...)
SELECT DISTINCT itemID FROM ItemsTags it, Tags t 
WHERE it.tagID = t.ID AND t.tag IN ('p1','p2','p3') AND t.tag NOT IN ('p4','p5','p6')
SELECT i.title
  FROM items i
 WHERE EXISTS(SELECT * FROM join_table j JOIN tags t ON t.id = j.tag_id WHERE j.item_id = i.id AND t.name = 'tag1')
   AND NOT EXISTS(SELECT * FROM join_table j JOIN tags t ON t.id = j.tag_id WHERE j.item_id = i.id AND t.name = 'tag2')

servidor SQL faz um trabalho bom sobre esta construção, mas a Oracle pode precisar de alguma insinuando para obtê-lo direito (pelo menos ele fez 5 anos atrás).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top