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

使用GROUP BY后MySQL UNION查询仍返回重复值问题排查

解决新闻列表重复问题 & 原查询GROUP BY无效的原因

首先,咱们先搞定重复的问题,再聊聊为什么你的GROUP BY没起作用。

一、正确的查询方案(避免重复)

你的核心需求是:获取所有由17152创建的新闻(不管是英文还是西班牙文),且同一新闻只返回一次。最直接的方式是从主表z_news_master出发,判断它是否关联到任意一个语言表中符合条件的记录,而不是从语言表反向关联主表再合并。

方案1:用EXISTS精准筛选(推荐)

这个方案逻辑清晰,性能也不错,直接从主表取唯一记录:

SELECT 
    m.id, 
    m.title, 
    m.created_by, 
    m.publish_up, 
    m.state
FROM z_news_master m
WHERE 
    -- 存在英文关联记录且创建者是17152
    EXISTS (
        SELECT 1 
        FROM z_news_english e 
        WHERE e.reference_id = m.id AND e.created_by = 17152
    )
    -- 或者存在西班牙文关联记录且创建者是17152
    OR EXISTS (
        SELECT 1 
        FROM z_news_spanish s 
        WHERE s.reference_id = m.id AND s.created_by = 17152
    )
-- 按需排序,比如按发布时间倒序
ORDER BY m.publish_up DESC;

方案2:如果需要语言表的额外字段

如果你还想获取语言表的某些信息(比如区分新闻是英文还是西班牙文),可以用LEFT JOIN加DISTINCT确保主表记录唯一:

SELECT DISTINCT
    m.id, 
    m.title, 
    m.publish_up, 
    m.state,
    -- 取任意一个存在的创建者(这里都是17152,所以结果一致)
    COALESCE(e.created_by, s.created_by) AS created_by,
    -- 可选:标记新闻的语言类型
    CASE 
        WHEN e.id IS NOT NULL THEN 'English'
        WHEN s.id IS NOT NULL THEN 'Spanish'
        ELSE 'Unknown'
    END AS language
FROM z_news_master m
LEFT JOIN z_news_english e 
    ON m.id = e.reference_id AND e.created_by = 17152
LEFT JOIN z_news_spanish s 
    ON m.id = s.reference_id AND s.created_by = 17152
-- 确保至少关联一个语言表的记录
WHERE e.id IS NOT NULL OR s.id IS NOT NULL
ORDER BY m.publish_up DESC;

二、为什么你的原查询GROUP BY没解决重复?

咱们拆解一下你的原查询逻辑和问题根源:

  1. UNION的去重规则:UNION本身会自动去重,但前提是两条记录的所有列值完全一致。如果你的两个子查询返回的记录,虽然id相同,但其他列(比如title、publish_up)来自不同的表且值不同(比如英文标题和西班牙文标题不一样),UNION会认为这是两条不同的记录,不会合并。
  2. GROUP BY的作用限制:你在UNION之后加GROUP BY id,理论上会把同一id的记录合并成一行,但这里有两个问题:
    • 如果你的SQL模式开启了ONLY_FULL_GROUP_BY(MySQL默认开启),这个查询会直接报错,因为title、created_by等列不在GROUP BY中,也没有聚合函数(比如MAX(title))。
    • 如果没开启ONLY_FULL_GROUP_BY,数据库会随机选择分组内某一行的列值返回,但你可能会误以为还是重复(其实是同一id的一条记录,但内容是其中一个语言的),而且这种行为是不可控的。
  3. 子查询的ORDER BY无效:另外,你在子查询里加的ORDER BY c.id DESC其实是无效的——在UNION的子查询中,ORDER BY如果没有搭配LIMIT,数据库会忽略这个排序,所以你的子查询排序不会生效。

简单说,你的原查询思路是从语言表“拉”主表数据,同一主表会被两个语言表各拉一次,导致生成两条记录;而如果这两条记录的列值有差异,UNION和GROUP BY都无法按你预期的方式合并它们。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:44:12