pandronic
pandronic

Reputation: 651

How to select all articles with a tag and all article's tags with one MySQL query?

I have 3 tables: articles (id, title, content), tags (id, tag) and tags2all (id, iditem, idtag, module). I want to select all articles with a certain tag, but in the resulting list I want to be able to also display each article's tags.

At the moment I'm using this query to display the list of articles:

SELECT GROUP_CONCAT(t.tag SEPARATOR ', ') AS tags,a.* FROM articles AS a LEFT JOIN tags2all AS ta ON ta.iditem=a.id AND ta.module='articles' JOIN tags AS t ON ta.idtag=t.id GROUP BY a.id HAVING a.title IS NOT NULL

It seems to work reasonably well, but I can't seem to figure what to add to the query to display only the articles that have a certain tag.

If I add WHERE t.id=3, it selects the correct articles, but the tag list will contain only that tag.

Upvotes: 1

Views: 1039

Answers (2)

Tom Mac
Tom Mac

Reputation: 9853

This seemed to work ok for me:

select a.*
from
(
SELECT GROUP_CONCAT(t.tag SEPARATOR ', ') AS tags,a.id,a.title,a.content
FROM articles AS a LEFT JOIN tags2all AS ta ON ta.iditem=a.id 
AND ta.module='articles' JOIN tags AS t ON ta.idtag=t.id 
GROUP BY a.id HAVING a.title IS NOT NULL
) a inner join tags2all t2a on t2a.iditem = a.id
inner join tags t on t.id = t2a.idtag
where t.id = 3;

Here's the DDL and data I used:

create table articles (id int unsigned not null primary key, title varchar(50), content varchar(50));

create table tags (id int unsigned not null primary key, tag varchar(50));

create table tags2all (id int unsigned not null primary key, iditem int unsigned not null, idtag int unsigned not null, module varchar(50));

insert into articles values (1,"Article1","Some content");
insert into articles values (2,"Article2","Some content");
insert into articles values (3,"Article3","Some content");

insert into tags values (1,"Tag1");
insert into tags values (2,"Tag2");
insert into tags values (3,"Tag3");
insert into tags values (4,"Tag4");
insert into tags values (5,"Tag5");
insert into tags values (6,"Tag6");
insert into tags values (7,"Tag7");

insert into tags2all (id,iditem,idtag,module) values (1,1,1,"articles");
insert into tags2all (id,iditem,idtag,module) values (2,1,2,"articles");
insert into tags2all (id,iditem,idtag,module) values (3,1,3,"articles");
insert into tags2all (id,iditem,idtag,module) values (4,2,3,"articles");
insert into tags2all (id,iditem,idtag,module) values (5,2,4,"articles");
insert into tags2all (id,iditem,idtag,module) values (6,2,5,"articles");
insert into tags2all (id,iditem,idtag,module) values (7,3,3,"articles");
insert into tags2all (id,iditem,idtag,module) values (8,3,4,"articles");
insert into tags2all (id,iditem,idtag,module) values (9,3,7,"articles");

Upvotes: 1

hungneox
hungneox

Reputation: 9829

I'm not sure but let's try

SELECT GROUP_CONCAT(t.tag SEPARATOR ', ') AS tags,a.* FROM articles AS a 
LEFT JOIN tags2all AS ta ON ta.iditem=a.id AND ta.module='articles' 
JOIN tags AS t ON ta.idtag=t.id 
JOIN tags AS t1 ON ta1.idtag=t.id
GROUP BY a.id HAVING a.title IS NOT NULL

Upvotes: 0

Related Questions