foreach循环嵌套SQL查询出现重复结果,求有效去重方案
解决敏感词查询重复结果的问题
问题根源
你当前的逻辑是循环每个敏感词单独执行一次SQL查询,若某条聊天消息包含多个敏感词(例如同时包含"bad"和"badword"),这条消息会被多次查询返回,即使单条SQL用了SELECT DISTINCT,循环输出时仍会重复显示。
解决方案
方法1:一次性SQL查询(推荐,高效且安全)
将所有敏感词的匹配条件用OR拼接成单条SQL,只执行一次查询,从根源避免重复结果,同时解决原代码的SQL注入风险:
<?php $bad_word = ["badword", "bad_word", "bad", "frick", "heck"]; // 构造每个敏感词对应的LIKE占位符 $placeholders = array_fill(0, count($bad_word), 'msg LIKE ?'); // 拼接WHERE条件 $whereClause = implode(' OR ', $placeholders); // 预处理SQL语句 $stmt = $con->prepare("SELECT DISTINCT username, msg, date_log, time_log FROM chat_logs WHERE $whereClause"); // 为每个敏感词生成带通配符的参数 $params = array_map(function($word) { return "%$word%"; }, $bad_word); // 绑定参数类型(所有参数都是字符串,用's'表示) $types = str_repeat('s', count($params)); $stmt->bind_param($types, ...$params); $stmt->execute(); $result = $stmt->get_result(); // 输出结果 while($bad_msg = mysqli_fetch_array($result)){ echo ' <div class="msg"> <div class="msg-top"> <p><b>'.$bad_msg['username'].'</b> '.$bad_msg['date_log'].' - '.$bad_msg['time_log'].'</p></div>'; if(!empty($bad_msg['msg'])){ echo '<span>'.$bad_msg['msg'].'</span>'; } echo '</div>'; } ?>
方法2:PHP层面去重
如果不想修改SQL逻辑,可以在PHP中用数组存储结果时,通过唯一标识过滤重复记录:
<?php $bad_word = ["badword", "bad_word", "bad", "frick", "heck"]; $uniqueResults = []; foreach($bad_word as $word){ $get_flags = $con->query("SELECT DISTINCT username, msg, date_log, time_log FROM chat_logs WHERE msg LIKE '%$word%'"); while($bad_msg = mysqli_fetch_array($get_flags)){ // 用消息内容+日期+时间生成唯一键,确保同一条消息只存一次 $key = $bad_msg['msg'] . '_' . $bad_msg['date_log'] . '_' . $bad_msg['time_log']; $uniqueResults[$key] = $bad_msg; } } // 遍历去重后的结果输出 foreach($uniqueResults as $bad_msg){ echo ' <div class="msg"> <div class="msg-top"> <p><b>'.$bad_msg['username'].'</b> '.$bad_msg['date_log'].' - '.$bad_msg['time_log'].'</p></div>'; if(!empty($bad_msg['msg'])){ echo '<span>'.$bad_msg['msg'].'</span>'; } echo '</div>'; } ?>
注意事项
- 原代码直接将变量拼接进SQL存在SQL注入风险,方法1使用预处理语句彻底解决了这个问题,更推荐使用。
- 方法1只需执行一次数据库查询,性能远优于循环多次查询的方式。
内容的提问来源于stack exchange,提问作者mysh randy
相关产品推荐
相关产品推荐

