WordPress双表关联查询结果重复,如何实现去重?
问题根源与解决方案
核心问题:SQL关联逻辑错误
你的重复显示问题完全来自这条SQL查询:
$q2_results = $wpdb->get_results("SELECT $q2_item.id, $q2_item.listID, $q2_item.itemDESC, $q2_item.creator, $q2_item.title, $q2_read.userID, $q2_read.itemID, $q2_read.list FROM $q2_item INNER JOIN $q2_read ON $q2_item.id != $q2_read.itemID");
用!=做INNER JOIN的关联条件,会让plugin_items里的每一条记录,和plugin_read里所有itemID不匹配的记录生成一条结果。比如plugin_read有4条记录,一个未被标记的plugin_items条目就会生成4条重复结果,这就是重复次数随plugin_read记录数成倍增加的原因。
另外还有两个小问题:
- array_filter里的字符串拼接用了
+,PHP中字符串拼接要用.,而且$GLOBALS['a']如果是数字类型,不需要额外加单引号包裹 - 循环里每次都调用
wp_get_current_user(),没必要,应该提前获取一次
修复后的代码实现
直接在SQL里完成过滤和去重,效率比PHP处理数组高得多:
<div class="user-read"> <?php global $wpdb, $current_user; wp_get_current_user(); // 提前获取当前用户,避免循环重复调用 $q2_read = $wpdb->prefix.'plugin_read'; $q2_item = $wpdb->prefix.'plugin_items'; $target_list_id = intval($GLOBALS['a']); // 转成整数防止SQL注入 // 用NOT EXISTS获取未被标记的条目,同时过滤指定listID,并且只取当前用户或管理员创建的内容 $q2_results = $wpdb->get_results($wpdb->prepare( "SELECT i.id, i.listID, i.itemDESC, i.creator, i.title FROM $q2_item i WHERE i.listID = %d AND (i.creator = %d OR i.creator = 'administrator') AND NOT EXISTS ( SELECT 1 FROM $q2_read r WHERE r.itemID = i.id )", $target_list_id, $current_user->ID )); ?> <?php foreach($q2_results as $i ) : ?> <div class="user-wrap"> <div class="inner-wrap"> <div> <span class="check"> <form> <input type="checkbox" value="<?php echo esc_attr($i->id);?>"> </form> </span> </div> <div> <b><?php echo esc_html($i->title); ?></b><br> <?php echo esc_html($i->itemDESC) ; ?> </div> </div> </div> <?php endforeach; ?> </div>
关键优化点
- SQL逻辑修正:用
NOT EXISTS替代错误的JOIN条件,确保每个plugin_items条目只返回一次(未被标记的) - 安全加固:用
$wpdb->prepare()和intval()防止SQL注入,用esc_attr()/esc_html()处理输出内容,符合WordPress安全规范 - 性能优化:提前获取当前用户,把所有过滤逻辑放到SQL层,减少PHP数组处理的开销
- 代码简化:去掉冗余的else分支,用
foreach : ... endforeach语法让代码更易读
内容的提问来源于stack exchange,提问作者CodeChic
相关产品推荐
相关产品推荐

