如何拆分rooms表逗号分隔字段并关联utilities表获取设备名
解决逗号分隔ID字段关联另一表获取对应名称的问题
看起来你已经找对方向了,但代码里还有几个小问题导致结果不符合预期,我帮你调整修正一下:
首先看你的joinDevRoom方法,这里有几个需要修正的点:
- 表名写错了,应该是
rooms而非room - SQL查询的字段和
bind_result绑定的变量不匹配——你选了房间名和聚合后的设备名,但绑定的是$id和$utilities,顺序完全对应不上 - 可以给
GROUP_CONCAT加个排序规则,让设备名称展示得更整齐
修正后的joinDevRoom方法:
public function joinDevRoom() { $arr = array(); $statement = $this->conn->prepare(" SELECT r.id, r.name, GROUP_CONCAT(u.device ORDER BY u.device ASC) AS utilities FROM rooms r LEFT JOIN utilities u ON FIND_IN_SET(u.id, r.utilities) > 0 GROUP BY r.id, r.name "); // 对应SQL里的三个字段:房间ID、房间名、拼接后的设备名 $statement->bind_result($id, $name, $utilities); $statement->execute(); while ($statement->fetch()) { $arr[] = [ "id" => $id, "name" => $name, // 处理没有关联设备的房间,显示友好默认文本 "utilities" => $utilities ?: "无可用设备" ]; } $statement->close(); return $arr; }
然后是你的confroomreport.php,现在的两个循环会把所有房间名先输出完,再输出所有设备列,直接导致表格结构错乱。其实你完全不需要同时调用getConfRoomList和joinDevRoom,直接用joinDevRoom返回的整合数据即可,用foreach循环也更简洁直观:
<?php require_once("db.php"); // 直接获取已经关联好房间和对应设备的数据 $roomWithUtilities = $conn->joinDevRoom(); ?> <table border='1'> <tr> <th>Room</th> <th>Utilities</th> </tr> <?php foreach($roomWithUtilities as $room) { ?> <tr> <!-- 用htmlspecialchars防止XSS攻击,避免特殊字符破坏页面结构 --> <td><?php echo htmlspecialchars($room['name']); ?></td> <td><?php echo htmlspecialchars($room['utilities']); ?></td> </tr> <?php } ?> </table>
最后给你一个数据库设计的小建议:逗号分隔的字段其实不符合数据库设计的第一范式,当数据量变大时,FIND_IN_SET的查询性能会明显下降。更规范的做法是新建一个中间关联表room_utilities,结构如下:
| room_id | utility_id |
|---|---|
| 1 | 1 |
| 1 | 3 |
| 1 | 4 |
对应的查询SQL会变成:
SELECT r.name, GROUP_CONCAT(u.device ORDER BY u.device ASC) AS utilities FROM rooms r LEFT JOIN room_utilities ru ON r.id = ru.room_id LEFT JOIN utilities u ON ru.utility_id = u.id GROUP BY r.id, r.name
这种方式不仅查询性能更好,后续维护(比如添加/删除房间的设备)也会更灵活方便。
内容的提问来源于stack exchange,提问作者Tngld
相关产品推荐
相关产品推荐

