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

MySQL中如何结合JOIN与HAVING?GROUP BY后关联表去重求助

解决MySQL关联查询后结果重复的问题

嘿,我来帮你捋捋这个问题!你遇到的重复问题,根源在于关联操作和GROUP BY的顺序搞反了。

原本单独对tbl_warning按staff_id分组时,每个staff_id只会返回一条记录(前提是你的MySQL没有开启ONLY_FULL_GROUP_BY,这里先不展开这个规则),但当你先关联tbl_employment和tbl_staff再分组时,关联过程会先把所有匹配的行拉出来——如果某个staff_id在关联表中有多条对应记录(比如员工有多个雇佣记录),就会生成多条临时行,之后再分组就可能出现重复的结果,甚至破坏你原本想要的“每个staff_id唯一”的逻辑。

下面给你几个针对性的解决方案:

方案1:先分组统计,再关联其他表

这是最直接的解决思路:先把tbl_warning按staff_id分组的结果作为子查询,再和其他表做关联。这样子查询里每个staff_id只有一条记录,关联后自然不会出现重复。

示例SQL:

SELECT 
    w.id, 
    w.staff_id, 
    w.note, 
    w.warning_date,
    e.com_id AS comid,
    s.name,
    s.gender
FROM (
    -- 先完成分组逻辑,得到每个staff_id对应的警告记录
    SELECT id, staff_id, note, warning_date 
    FROM tbl_warning 
    GROUP BY staff_id 
    HAVING COUNT(staff_id) > 0
) AS w
-- 关联雇佣表和员工表
JOIN tbl_employment e ON w.staff_id = e.staff_id
JOIN tbl_staff s ON w.staff_id = s.staff_id;

⚠️ 注意:如果tbl_warning里同一个staff_id有多条警告记录,上面的子查询会随机选一条(MySQL在未开启ONLY_FULL_GROUP_BY时的默认行为)。如果你需要特定的记录(比如最新的警告),可以调整子查询,比如:

SELECT 
    id, staff_id, note, warning_date 
FROM tbl_warning w
WHERE warning_date = (
    SELECT MAX(warning_date) FROM tbl_warning WHERE staff_id = w.staff_id
);

方案2:用窗口函数筛选唯一staff_id的指定记录

如果你需要保留每个staff_id的特定警告记录(比如最新的),同时关联其他表,窗口函数ROW_NUMBER()会是更灵活的选择:

SELECT 
    id, 
    staff_id, 
    note, 
    warning_date,
    comid,
    name,
    gender
FROM (
    SELECT 
        w.id, 
        w.staff_id, 
        w.note, 
        w.warning_date,
        e.com_id AS comid,
        s.name,
        s.gender,
        -- 按staff_id分组,给每条记录按警告日期倒序编号
        ROW_NUMBER() OVER (PARTITION BY w.staff_id ORDER BY w.warning_date DESC) AS rn
    FROM tbl_warning w
    JOIN tbl_employment e ON w.staff_id = e.staff_id
    JOIN tbl_staff s ON w.staff_id = s.staff_id
) AS t
-- 只取每个staff_id的第一条(最新的)记录
WHERE rn = 1;

方案3:用DISTINCT去重(适合保留所有警告记录但去重关联结果)

如果你的需求是显示所有警告记录,但要去掉因为关联表导致的重复行,可以用DISTINCT关键字:

SELECT DISTINCT
    w.id, 
    w.staff_id, 
    w.note, 
    w.warning_date,
    e.com_id AS comid,
    s.name,
    s.gender
FROM tbl_warning w
JOIN tbl_employment e ON w.staff_id = e.staff_id
JOIN tbl_staff s ON w.staff_id = s.staff_id;

这个方法适合当关联表中同一个staff_id有重复记录,但你只需要保留唯一的字段组合时使用。

另外还要提醒你:如果tbl_employment或tbl_staff中一个staff_id对应多条有效记录(比如员工换过公司,有多个com_id),那你得先确定要取哪个值,比如最新的雇佣记录,这时候可能需要先对关联表也做分组处理哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:03:44