I believe that I am having a bad database design and need some help to improve it. I am having three tables for my blog posts.
Posts
-id
-title
Categories
-id
-name
CategoryBindings
-id
-postId
-categoryId
Let say that I have this data:
Posts
1 Title1
2 Title2
Categories
1 category1
2 category2
CategoryBindings
1 1 1
2 1 2
3 2 1
The query I am using now to get my posts with their categories are
SELECT `p`.*, `cb`.`categoryId`, `c`.`name` AS `categoryName`
FROM `Posts` AS `p`
LEFT JOIN `CategoryBindings` AS `cb` ON p.id = cb.postId
LEFT JOIN `Categories` AS `c` ON cb.categoryId = c.id
Which gives following result:
1 Title1 1 category1
1 Title1 2 cateogry2
2 Title2 1 cateogry1
I am getting a dublicate of post 1 since their are two categoryBindings for it. I have written a code that with php fixes the result so that I get.
1 Title1 array(1 category1, 2 category2)
2 Title2 array(1 category1)
and it worked fine until a remembered that I need to use limit with in my queries. I want to show 10 posts per page but I can't use limits since my query returns duplicated rows. Is it a way to change my query in order to get it to work as I want to, or do I need to redesign my tables? If so how would you recommend me to redesign my tables?
You can use GROUP_CONCAT
AND CONCAT_WS
:
SELECT `p`.`id`, `p.title`, GROUP_CONCAT(CONCAT_WS(' ', `cb`.`categoryId`, `c`.`name`)) AS `categoryNames`
FROM `Posts` AS `p`
LEFT JOIN `CategoryBindings` AS `cb` ON p.id = cb.postId
LEFT JOIN `Categories` AS `c` ON cb.categoryId = c.id
GROUP BY id, title
By the way: You should not SELECT *
in code, better to write what you want explicitly. It avoids unneeded overhead if you add a column that is not used in code and will fail early if you delete/rename a column.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.