PHP+MySQL关联查询文章分类结果重复,需实现分类名逗号分隔展示
实现方案
你可以从SQL聚合、PHP重组两个方向调整,优先推荐SQL层直接聚合的方案,代码更简洁性能更好。
方案1:SQL层使用GROUP_CONCAT聚合(推荐)
出现重复行的核心原因是JOIN关联后一篇文章对应N条分类关联记录就会返回N行,直接用MySQL内置的GROUP_CONCAT()函数按文章分组,把同文章下的分类名拼接成单个字段即可从根源解决问题。
注意你原代码里取文章标题的字段名写错了:表结构里标题字段是title,不是post_title,直接用会报字段不存在错误。
修改后的SQL语句:
SELECT p.post_id, p.title, p.date, GROUP_CONCAT(c.category_name SEPARATOR ',') AS category_names FROM tbl_post p INNER JOIN tbl_post_category pc ON p.post_id = pc.post_id INNER JOIN tbl_category c ON pc.category_id = c.category_id GROUP BY p.post_id, p.title, p.date ORDER BY p.post_id DESC
提示:MySQL默认
GROUP_CONCAT单字段最大拼接长度为1024字符,如果单篇文章关联分类较多可能出现内容截断,可在执行查询前先运行SET SESSION group_concat_max_len = 10240;临时调大当前连接的拼接长度上限。
对应调整后的PHP代码:
<?php $i = 0; $sql = "SELECT p.post_id, p.title, p.date, GROUP_CONCAT(c.category_name SEPARATOR ',') AS category_names FROM tbl_post p INNER JOIN tbl_post_category pc ON p.post_id = pc.post_id INNER JOIN tbl_category c ON pc.category_id = c.category_id GROUP BY p.post_id, p.title, p.date ORDER BY p.post_id DESC"; $statement = $pdo->prepare($sql); $statement->execute(); $result = $statement->fetchAll(PDO::FETCH_ASSOC); foreach ($result as $row) { $i++; ?> <?php echo $i; ?> <?php echo $row['title']; ?> <?php echo $row['category_names']; ?> <?php } ?>
方案2:PHP层遍历重组数据(无需修改原SQL)
如果不想调整原有查询逻辑,可以保留原SQL语句,拿到查询结果后在PHP层按文章ID分组,收集同文章下的所有分类名后手动拼接,代码如下:
<?php $i = 0; $statement = $pdo->prepare("SELECT * FROM tbl_post JOIN tbl_post_category ON tbl_post.post_id = tbl_post_category.post_id INNER JOIN tbl_category ON tbl_post_category.category_id = tbl_category.category_id ORDER BY tbl_post.post_id DESC"); $statement->execute(); $rawResult = $statement->fetchAll(PDO::FETCH_ASSOC); // 按文章ID重组数据 $postList = []; foreach ($rawResult as $item) { $postId = $item['post_id']; if (!isset($postList[$postId])) { $postList[$postId] = [ 'post_id' => $postId, 'title' => $item['title'], 'date' => $item['date'], 'category_list' => [] ]; } $postList[$postId]['category_list'][] = $item['category_name']; } // 遍历输出处理后的数据 foreach ($postList as $row) { $i++; ?> <?php echo $i; ?> <?php echo $row['title']; ?> <?php echo implode(',', $row['category_list']); ?> <?php } ?>
额外优化建议
- 你提供的建表SQL存在两处语法错误,建议修正:
tbl_category建表语句末尾缺少分号,tbl_post_category表中post_id字段定义行末尾多了冗余逗号 - 三张表目前未设置主键、关联字段索引,数据量上来后JOIN查询性能会明显下降,建议给
tbl_post.post_id、tbl_category.category_id设置主键,给tbl_post_category.post_id、tbl_post_category.category_id加普通索引。
内容的提问来源于stack exchange,提问作者user3244304
相关产品推荐
相关产品推荐

