You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现多表订单查询并合并同订单商品为单行的问题

解决多订单商品合并展示的问题

你的问题核心是同一个订单的多个商品被拆分成了多行输出,这是因为你在循环查询每个订单ID后,直接逐行输出了查询到的每条商品记录,没有做合并处理。其实我们可以通过SQL的聚合函数一次性完成数据的合并和统计,效率更高也更简洁。

第一步:优化SQL查询语句

使用GROUP_CONCAT函数可以把同一个订单下的所有商品名合并成逗号分隔的字符串,SUM函数可以计算订单的总金额,再通过GROUP BY按订单ID分组,这样一次查询就能得到你需要的所有格式化数据:

SELECT 
    o.order_id,
    GROUP_CONCAT(i.item_name SEPARATOR ',') AS orders,
    SUM(i.price) AS price,
    o.user_id,
    u.username
FROM orders o
LEFT JOIN order_item oi ON o.order_id = oi.order_id
LEFT JOIN item i ON oi.item_id = i.item_id
LEFT JOIN users u ON o.user_id = u.user_id
GROUP BY o.order_id
ORDER BY o.order_id;

这里用LEFT JOIN而不是INNER JOIN是为了确保像order_id=7这种没有关联商品的订单也能被查询到(如果你的业务允许空商品的话),如果确定所有订单都有商品,用INNER JOIN也可以。

第二步:修改PHP代码逻辑

不需要再循环遍历每个可能的订单ID了,直接执行上面的SQL,然后循环结果集输出即可,每个订单自然就是一行:

// 执行优化后的SQL
$sql = "SELECT 
            o.order_id,
            GROUP_CONCAT(i.item_name SEPARATOR ',') AS orders,
            SUM(i.price) AS price,
            o.user_id,
            u.username
        FROM orders o
        LEFT JOIN order_item oi ON o.order_id = oi.order_id
        LEFT JOIN item i ON oi.item_id = i.item_id
        LEFT JOIN users u ON o.user_id = u.user_id
        GROUP BY o.order_id
        ORDER BY o.order_id";

$res = mysqli_query($conn, $sql);

// 输出表格头部(如果需要的话)
echo "<table><tr><th>order id</th><th>orders</th><th>price</th><th>user_id</th><th>username</th></tr>";

// 循环输出每个订单的行
while ($result = mysqli_fetch_assoc($res)) {
    $order_id = $result['order_id'];
    $items = $result['orders'] ?? '无商品'; // 处理没有商品的情况
    $total_price = $result['price'] ?? 0;
    $user_id = $result['user_id'];
    $username = $result['username'];
    
    echo "<tr>
            <td style='border-top:1px solid #5C1916;'>$order_id</td>
            <td style='border-top:1px solid #5C1916;'>$items</td>
            <td style='border-top:1px solid #5C1916;'>$total_price</td>
            <td style='border-top:1px solid #5C1916;'>$user_id</td>
            <td style='border-top:1px solid #5C1916;'>$username</td>
          </tr>";
}

echo "</table>";

额外提示:避免SQL注入风险

你原来的代码中直接把$i拼到SQL语句里,存在SQL注入的安全隐患。如果以后需要动态传入参数,建议使用预处理语句,比如:

// 示例:预处理查询单个订单
$stmt = $conn->prepare("SELECT ... WHERE o.order_id = ?");
$stmt->bind_param("i", $order_id);
$stmt->execute();
$result = $stmt->get_result();

这样能有效防止SQL注入攻击,让代码更安全。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:09:16