Many set operations can be done with compound queries:
SELECT *
FROM bookmarks
WHERE bm_id IN (SELECT bookmark_id FROM bookmarktag WHERE tag_id = 2
INTERSECT
SELECT bookmark_id FROM bookmarktag WHERE tag_id = 3)
Pregunta
I'm creating a simple bookmark-management webapp in Python(Flask) but mainly to get experience in SQL (using sqlite) though. I am using tags which we can link to the bookmarks in many-to-many fashion(similar to stackoverflow questions). I have created 3 tables as below :
bookmarks :
bm_id | bm_title | bm_link
1 | bm_title1 | bm_link1
2 | bm_title2 | bm_link2
3 | bm_title3 | bm_link3
4 | bm_title4 | bm_link4
tags :
bm_id | t_name
1 | t_name1
2 | t_name2
3 | t_name3
4 | t_name4
bookmarktag :
bmt_id | bookmark_id | tag_id
3 | 3 | 3
5 | 3 | 2
6 | 4 | 3
7 | 4 | 2
1 | 1 | 1
2 | 1 | 2
4 | 3 | 1
8 | 2 | 3
I know how to list all the bookmarks associated with a particular tag.
But I want to know how to list bookmarks common to 2 particular tags. For example, if I were to search for bookmarks common to tag 2 & 3; it should show only bookmarks 3 & 4.
I've only been able to list all the bookmarks associated with tags 2 & 3 using SELECT * FROM bookmarktag bmt WHERE bmt.tag_id=2 OR bmt.tag_id=3;
. But as you may know it lists all the bookmarks linked to tags 2 & 3.
Thank you!
Solución
Many set operations can be done with compound queries:
SELECT *
FROM bookmarks
WHERE bm_id IN (SELECT bookmark_id FROM bookmarktag WHERE tag_id = 2
INTERSECT
SELECT bookmark_id FROM bookmarktag WHERE tag_id = 3)
Otros consejos
This is an example of a "set-within-sets" query. I like to solve these using group by
and having
:
select bookmark_id
from bookmarktag bmt
group by bookmark_id
having sum(tag_id = 2) > 0 and
sum(tag_id = 3) > 0;
Each condition in the having
clause is looking for one of the tags that you specify. Each requires that the tag appear at least one time.