PHP中使用两个SQL表数据时结果重复的问题解决
问题修复:商品重复显示与积分查询优化
问题根源
你使用了CROSS JOIN,这会生成笛卡尔积——shopitems的每一条记录都会和listings的每一条记录强制配对。如果listings表中有3条用户数据,6个商品就会得到6×3=18条重复结果,这就是重复显示的原因。
修复方案
你只需要当前登录用户的points字段,完全不需要对两张表做全量关联。正确的做法是:
- 先单独查询当前用户的积分余额
- 再查询所有商品,用拿到的积分逐个判断购买状态
修改后的代码
<?php include('../config.php'); try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 第一步:获取当前登录用户的积分(假设用session存储用户ID,listings表有user_id字段) // 请根据实际登录逻辑替换$_SESSION['user_id']为正确的用户标识 $user_id = $_SESSION['user_id']; $stmt_balance = $conn->prepare("SELECT points FROM listings WHERE user_id = ?"); $stmt_balance->execute([$user_id]); $user_data = $stmt_balance->fetch(PDO::FETCH_ASSOC); $balance = $user_data['points'] ?? 0; // 处理用户无记录的情况,默认0积分 // 第二步:查询所有商品,无需关联listings表 $stmt = $conn->prepare("SELECT * FROM shopitems"); $stmt->execute(); $stmt->setFetchMode(PDO::FETCH_ASSOC); // 将fetchMode放在循环外,提升效率 while($row = $stmt->fetch()) { $cost = $row['itemcost']; $status = $balance < $cost ? 'Not enough points' : 'Purchase'; echo ' <div class="col-lg mb-md-0 mb-4"> <div class="card border rounded shadow-none"> <div class="card-body"> <div class="my-3 pt-2 text-center"> <img src="'.$row['itemimage'].'" alt="Basic Image" height="140"> </div> <h3 class="card-title text-center text-capitalize mb-1">'.$row['itemname'].'</h3> <div class="text-center"> <div class="d-flex justify-content-center"> <sup class="h6 pricing-currency mt-3 mb-0 me-1 text-primary">P</sup> <h1 class="display-4 mb-0 text-primary">'.$row['itemcost'].'</h1> </div> </div> <br/> <a href="./protected/webhook-alerts/shop-purchase.php?desc='.$row['itemdesc'].'" method="post" type="submit" class="btn btn-primary d-grid w-100 post">'.$status.'</a> </div> </div> </div> '; } } catch(PDOException $e) { echo "Error: " . $e->getMessage(); } ?>
关键修改点
- 移除
CROSS JOIN,彻底避免笛卡尔积导致的重复结果 - 单独查询当前用户积分,避免不必要的全表关联
- 将
setFetchMode移到循环外,减少重复执行的开销 - 增加积分默认值处理,避免用户无记录时出现报错
补充说明
如果你的listings表没有user_id字段,或者用户登录逻辑不同,请根据实际情况调整查询用户积分的SQL语句,核心原则是只获取当前用户的积分数据,而非全表的积分记录。
内容的提问来源于stack exchange,提问作者The Major
相关产品推荐
相关产品推荐

