MySQL - select all items with multiple hashtags

2019-09-17 07:36发布

I'm making hashtag system for my webpage, and have three tables:

  • items - ID and some others
  • tags - ID and name
  • item_tags - junction table with IDitem and IDtag

Selecting all items with given hashtag is pretty easy:

SELECT items.* FROM items
join item_tags on items.ID=item_tags.IDitem
join tags on item_tags.IDtag=tags.ID
where tags.name="something";

Question is, what should I do if I want to select all items with multiple tags, for example, find all items tagged as cat and animal?

I've thought about making temporary table, inserting all items with first tag, then leaving those with second tag, then third, then fourth and so on, but it doesn't look too good and too fast.

2条回答
我欲成王,谁敢阻挡
2楼-- · 2019-09-17 08:18

Just find all that match both tags, using IN. Like this:

SELECT DISTINCT items.* FROM items 
INNER JOIN item_tags on items.ID=item_tags.IDitem 
INNER JOIN tags on item_tags.IDtag=tags.ID 
WHERE tags.name="something"
AND items.* IN (
    SELECT items.* FROM items 
    INNER JOIN item_tags on items.ID=item_tags.IDitem 
    INNER JOIN tags on item_tags.IDtag=tags.ID 
    WHERE tags.name="somethingelse"
);
查看更多
来,给爷笑一个
3楼-- · 2019-09-17 08:26

well you know your list, so that is a simple string. and you know your count. these can be jammed into a mysql Prepared Statement and executed.

But below it is with the list and count plopped in just for demo purposes.

create table items
(   id int not null
);

create table tags
(   id int not null,
    name varchar(50)
);

create table item_tags
(   iid int not null,
    tid int not null
);

insert items (id) values (1),(2),(3),(4);
insert tags(id,name) values (1,'cat'),(2,'animal'),(3,'has nose');
-- note, everything has a nose so far:
insert item_tags (iid,tid) values (1,1),(1,3),(2,1),(2,3),(3,2),(3,3),(4,1),(4,2),(4,3);

select i.id,count(i.id)
from items i
join item_tags junc
on junc.iid=i.id
join tags t
on t.id=junc.tid and t.name in ('cat','animal')
group by i.id
having count(i.id)=2

-- only item 4 has both cat and animal (note nose is irrelevant)
查看更多
登录 后发表回答