hello, I need to display contents with their tags, and in same page all the tags of the page contents
the problem is having a limit on contents doesn't work if join tags on them (the number of tags change the number of select contents)


I have tables :

> contents
> tags
> link_contents_tags (id_tag, id_content)

I need to select contents with tags so for each content I display its tags
I have a pager so I limit the select of contents

the problem is if I make a
> select contents JOIN tags LIMIT xcontents
it won't work because of the y number of tags on each content
and to limit the number of tags is not a solution because it's unkwnown number (it can have no tag or 10)


so limit of 3 contents must display :

> [B]content_1 [/B]
>> tag1_content1
>> tag2_content1
>> tag3_content1

> [B]content_2[/B] 
>> (no tags)

> [B]content_3 [/B]
>> tag1_content3


but if I set
LIMIT 0, 3
on select contents join tags it'll not display 3 contents but just the first because of the join on x tags

A (not beautiful) SOLUTION

a solution is to

> select contents with search criterias
> read ids of found contents
> select tags JOIN links WHERE id_content IN (list ids found contents) ORDER BY id_content
> order tags in an array by content_id : arTags[content_id]=array rows tags
> display all contents, for each content display tags from tags array if exist 
> display next all contents from this page

it'll work with contents pager and unknown tags number by content
but it seems a little rude :)
two requests (can be ok) but a few loops on contents that I don't like

have any idea to simplify it?
I don't like to make ugly code :)

think's in advance

Edited by davehere: n/a

6 Years
Discussion Span
Last Post by davehere

You can limit the paged entries in a SELECT DISTINCT clause like that:

drop table if exists a;
drop table if exists b;
drop table if exists ab;
create table a (id integer);
create table b (id integer);
create table ab (a_id integer, b_id integer);
insert into a values (1),(2),(3),(4),(5);
insert into b values (1),(2),(3),(4),(5);
insert into ab values (1,1),(1,2),(1,3),(2,1),(2,2);

/* page 1 */
select a.*, b.*
from a 
inner join (
  select distinct a_id from ab order by a_id limit 0,1
) x
on a.id=x.a_id
inner join ab
on a.id=ab.a_id
inner join b
on ab.b_id=b.id
| id   | id   |
|    1 |    1 |
|    1 |    2 |
|    1 |    3 |

/* page 2 */
select a.*, b.*
from a 
inner join (
  select distinct a_id from ab order by a_id limit 1,1
) x
on a.id=x.a_id
inner join ab
on a.id=ab.a_id
inner join b
on ab.b_id=b.id
| id   | id   |
|    2 |    1 |
|    2 |    2 |
Votes + Comments
take time to write beautiful and complate example

If the tags are for displaying only, wouldn't a GROUP_CONCAT be useful ?

Votes + Comments
found just beautiful and perfect solution who saves me a lot of code

hey think for your quick - and good - responses ! :)

Smantscheff big think to have taken time to write complate example, it learns me better use to select distinct

and, wahou think pritaeas it's so beautiful! :)

so I'll use

GROUP_CONCAT(tag.name) as tags_names, GROUP_CONCAT(tag.type) as tags_types
GROUP BY content.id

and after in php explode on tags_names and tags_types to have them
there'll be a little time price in group by and working array but I think I won't find more simple

think you two you made my week!


I have also to get count contents of tags (a column in tags with update +1 when a new content on it) and order on count, but these works :

GROUP_CONCAT(tag.name ORDER BY tag.count_contents DESC) as tags_names, 
GROUP_CONCAT(tag.typename  ORDER BY tag.count_contents DESC) as tags_types, 
GROUP_CONCAT(CAST(tag.count_contents AS CHAR) ORDER BY tag.count_contents DESC) as tags_counts, 
JOIN tags
GROUP BY node.id

result :

content   | tagname          |  tagcount | ...
the clash | music rock punk  | 20 14 8

with for each content get its tags order by count of all contents on tags
(here there is a lot of contents on music, some on rock and a few on punk)

is it right for performing, or is it bad practice to have these 3 group_concat?

I'll have work on server to manage array of tags by contents but I think I can't avoid it (because in all cases I'll have to extract tags array from each content row)

think! :)

Edited by davehere: n/a


well I have found it I think it's ok with only one group_concat

GROUP_CONCAT(CONCAT(tag.typename,','), CONCAT(tag.name,','), CAST(tag.count_contents AS CHAR) ORDER BY tag.count_contents DESC SEPARATOR ';') as tags,

I think it's better performing with just one group_concat

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.