简体   繁体   中英

MySQL design, query, duplicated rows

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM