How can I implement boolean tag search in SQL?

Given a table of elements, a table of tags and a table of connections between them, which is a good and effective way to implement form requests:

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

I am using SQL. So, to find all the elements that match all the tags p1 ... pn and none of the n1 ... nk?

Is there a good “standard” solution for this?

+3
source share
5 answers

It's hard to say without knowing your schema, but something like this will work:

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

inner join with tags that should be included, and do anti-join (outer join + where the required column is null) tags that shouldn't be included

+2

, , :

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

, . , .

+2

It depends on how you store the tags in the database, but you probably need a statement IN:

SELECT tag FROM myTags WHERE tag IN ('p1','p2',...)
SELECT tag FROM myTags WHERE tag NOT IN ('p1','p2',...)
+2
source
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')
+1
source
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')

The SQL server does an excellent job of this construction, but Oracle may require some hint to figure it out (at least 5 years ago).

0
source

Source: https://habr.com/ru/post/1704075/


All Articles