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

MySQL多表关联查询报错求助:最后两个LEFT JOIN中p.id报错求替代方案

问题分析与解决方案

原SQL的核心错误出在最后两个LEFT JOIN的子查询中:where project_id = id完全是逻辑错误,你应该是想关联project表的id,但这里误把job表的project_id和job自身的id做了等值判断,而且这类子查询无法直接引用外部查询的p.id,导致查询失效。你的需求应该是获取每个项目对应的最早开工时间和最晚交付时间,以下是几种可行的实现方式:


方法1:使用窗口函数(MySQL 8.0及以上版本推荐)

利用ROW_NUMBER()窗口函数,按项目分组后分别对开工时间升序、交付时间降序排序,取每组第一条数据,逻辑清晰且效率较高:

SELECT 
    p.*,
    b.id AS brand,
    b.name AS brandname,
    j.id AS closed,
    c.name AS customername,
    l.name AS productline,
    u.user_name AS username,
    TIMESTAMPDIFF(HOUR, j1.start_date, j2.delivery_date) AS total_hour
FROM `project` AS p
LEFT JOIN customer AS c ON c.id = p.customer
LEFT JOIN brand AS b ON b.id = c.brand 
LEFT JOIN customer_product_line AS l ON l.id = p.product_line
LEFT JOIN users AS u ON u.id = p.created_by
LEFT JOIN (
    SELECT project_id, `status`, id 
    FROM job 
    WHERE `status` <> '1' 
    GROUP BY project_id, `status`
) AS j ON j.project_id = p.id
-- 获取每个项目最早的开工时间
LEFT JOIN (
    SELECT 
        project_id, 
        start_date,
        ROW_NUMBER() OVER(PARTITION BY project_id ORDER BY start_date ASC) AS rn
    FROM job
) AS j1 ON j1.project_id = p.id AND j1.rn = 1
-- 获取每个项目最晚的交付时间
LEFT JOIN (
    SELECT 
        project_id, 
        delivery_date,
        ROW_NUMBER() OVER(PARTITION BY project_id ORDER BY delivery_date DESC) AS rn
    FROM job
) AS j2 ON j2.project_id = p.id AND j2.rn = 1;

方法2:使用聚合函数(通用高效写法)

直接对job表按project_id分组,用MIN()取最早开工时间,MAX()取最晚交付时间,避免多次JOIN子查询,性能更优:

SELECT 
    p.*,
    b.id AS brand,
    b.name AS brandname,
    j.id AS closed,
    c.name AS customername,
    l.name AS productline,
    u.user_name AS username,
    TIMESTAMPDIFF(HOUR, job_stats.min_start, job_stats.max_delivery) AS total_hour
FROM `project` AS p
LEFT JOIN customer AS c ON c.id = p.customer
LEFT JOIN brand AS b ON b.id = c.brand 
LEFT JOIN customer_product_line AS l ON l.id = p.product_line
LEFT JOIN users AS u ON u.id = p.created_by
LEFT JOIN (
    SELECT project_id, `status`, id 
    FROM job 
    WHERE `status` <> '1' 
    GROUP BY project_id, `status`
) AS j ON j.project_id = p.id
-- 一次性统计每个项目的时间极值
LEFT JOIN (
    SELECT 
        project_id,
        MIN(start_date) AS min_start,
        MAX(delivery_date) AS max_delivery
    FROM job
    GROUP BY project_id
) AS job_stats ON job_stats.project_id = p.id;

方法3:兼容MySQL 5.x的关联子查询写法

如果你的MySQL版本不支持窗口函数,可以在SELECT语句中直接用关联子查询获取对应时间:

SELECT 
    p.*,
    b.id AS brand,
    b.name AS brandname,
    j.id AS closed,
    c.name AS customername,
    l.name AS productline,
    u.user_name AS username,
    TIMESTAMPDIFF(
        HOUR,
        (SELECT MIN(start_date) FROM job WHERE project_id = p.id),
        (SELECT MAX(delivery_date) FROM job WHERE project_id = p.id)
    ) AS total_hour
FROM `project` AS p
LEFT JOIN customer AS c ON c.id = p.customer
LEFT JOIN brand AS b ON b.id = c.brand 
LEFT JOIN customer_product_line AS l ON l.id = p.product_line
LEFT JOIN users AS u ON u.id = p.created_by
LEFT JOIN (
    SELECT project_id, `status`, id 
    FROM job 
    WHERE `status` <> '1' 
    GROUP BY project_id, `status`
) AS j ON j.project_id = p.id;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:29:59