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

SQL联表查询使用DISTINCT仍出现id重复的问题求解

问题根因

DISTINCT 本质是对查询返回的整行所有字段的组合值做去重,并非只针对你写在括号里的o.id字段生效——括号在这里只是普通的表达式包裹符号,不会改变DISTINCT的作用逻辑。
你的结果中重复id对应的excelID值不同,因此id + status + excelID的整行组合是唯一的,自然不会被DISTINCT过滤掉。

另外你原查询里存在两个冗余逻辑:

  • 子查询中SELECT DISTINCT(orderId) id, excelID FROM parcels的去重逻辑无效:当同一个orderId对应多个不同excelID时,DISTINCT会保留所有orderId+excelID的唯一组合,还是会返回同一个orderId的多条记录
  • LEFT JOIN后加WHERE p.id is not null的写法等价于直接写INNER JOIN,不需要额外做左连接再过滤空值
修改方案

要实现每个id仅返回单条记录,核心是对同一个订单关联到的多个包裹记录做分组聚合,按业务规则取其中一条excelID即可。

方案1:通用聚合写法(兼容所有SQL版本)

如果你的业务规则是取每个订单关联的最大/最小excelID,直接用GROUP BY聚合即可,写法最简单兼容性最好:

SELECT 
  o.id, 
  o.status,  
  -- 如需取最小excelID替换为MIN(p.excelID)即可
  MAX(p.excelID) AS excelID
FROM orders AS o
INNER JOIN parcels AS p 
  ON o.id = p.orderId
WHERE o.id IS NOT NULL
GROUP BY o.id, o.status

方案2:窗口函数写法(支持MySQL8.0+/PostgreSQL/SQL Server等主流数据库)

如果你需要更灵活的取数规则(比如按创建时间、excelID排序取指定位置的记录),可以用窗口函数ROW_NUMBER()实现,以下写法的返回结果和你给出的预期结果完全一致:

SELECT id, status, excelID
FROM (
  SELECT 
    o.id, 
    o.status, 
    p.excelID,
    ROW_NUMBER() OVER (PARTITION BY o.id ORDER BY p.excelID DESC) AS row_sort
  FROM orders AS o
  INNER JOIN parcels AS p 
    ON o.id = p.orderId
  WHERE o.id IS NOT NULL
) t
WHERE row_sort = 1

上述语句中PARTITION BY o.id表示按订单id分组,ORDER BY p.excelID DESC表示组内按excelID倒序排列,最后取每组排序为1的记录,就实现了每个id仅返回一条记录的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:12:20