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

MySQL关联单表最新行:PHP项目展示餐厅及最新评论求助

解决方案

1. 单条SQL查询语句

使用窗口函数ROW_NUMBER()可以确保每个餐厅只返回一条最新评论记录,彻底避免左连接导致的重复行问题:

SELECT 
    r.id AS restaurant_id,
    r.name,
    r.cuisine,
    r.address,
    r.image_file,
    rev.id AS review_id,
    rev.header,
    rev.content,
    rev.posted_at,
    rev.modified_at,
    u.username AS reviewer_username
FROM restaurants r
LEFT JOIN (
    SELECT 
        *,
        -- 按餐厅分组,先按发布时间倒序,再按修改时间倒序,取每组第一条
        ROW_NUMBER() OVER (PARTITION BY restaurant_id ORDER BY posted_at DESC, modified_at DESC) AS rn
    FROM reviews
) rev ON r.id = rev.restaurant_id AND rev.rn = 1
LEFT JOIN users u ON rev.user_id = u.id;

如果你的数据库不支持窗口函数(如旧版MySQL),可以用子查询关联最大时间的替代方案:

SELECT 
    r.id AS restaurant_id,
    r.name,
    r.cuisine,
    r.address,
    r.image_file,
    rev.id AS review_id,
    rev.header,
    rev.content,
    rev.posted_at,
    rev.modified_at,
    u.username AS reviewer_username
FROM restaurants r
LEFT JOIN (
    SELECT restaurant_id, MAX(posted_at) AS latest_post_time
    FROM reviews
    GROUP BY restaurant_id
) latest_rev ON r.id = latest_rev.restaurant_id
LEFT JOIN reviews rev ON rev.restaurant_id = latest_rev.restaurant_id AND rev.posted_at = latest_rev.latest_post_time
LEFT JOIN users u ON rev.user_id = u.id;

注:第二种方案如果遇到同一餐厅同一时间有多条评论,可能返回重复行,优先推荐窗口函数方案。

2. PHP单个foreach循环实现展示

查询结果集中每一行对应一个餐厅(含最新评论或空值),直接循环即可完成展示:

// 假设$pdo是你的数据库连接实例
$stmt = $pdo->query($sql);
$restaurants = $stmt->fetchAll(PDO::FETCH_ASSOC);

foreach ($restaurants as $restaurant) {
    // 输出餐厅基础信息
    echo "<div class='restaurant-card'>";
    echo "<h2>{$restaurant['name']}</h2>";
    echo "<p>菜系:{$restaurant['cuisine']}</p>";
    echo "<p>地址:{$restaurant['address']}</p>";
    if (!empty($restaurant['image_file'])) {
        echo "<img src='{$restaurant['image_file']}' alt='{$restaurant['name']} 门店图'>";
    }

    // 输出最新评论(存在则显示)
    if (!empty($restaurant['review_id'])) {
        echo "<div class='latest-review'>";
        echo "<h3>最新评论:{$restaurant['header']}</h3>";
        echo "<p>{$restaurant['content']}</p>";
        echo "<p>评论人:{$restaurant['reviewer_username']} | 发布时间:{$restaurant['posted_at']}</p>";
        if ($restaurant['modified_at'] !== $restaurant['posted_at']) {
            echo "<p>最后修改:{$restaurant['modified_at']}</p>";
        }
        echo "</div>";
    }
    echo "</div>";
}

这样就通过单条SQL和单个foreach循环完成了需求,每个餐厅只会被处理一次,不会出现重复行问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:27:20