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

Postgres使用LEFT JOIN时不借助DISTINCT避免重复行的方案咨询

多表LEFT JOIN重复行非DISTINCT去重方案

你的场景下重复问题的核心诱因是:Purchase Discount表单Purchase ID对应2条记录,LEFT JOIN后会将上游匹配的Purchase、Purchase Item、Item记录直接复制为2份,后续聚合时就会出现ID重复、计数翻倍的问题。无需DISTINCT的优化方案有两类,性能远高于全局去重:

方案1:多端表预聚合后再关联

在关联Purchase Discount之前,先对该表按关联键(通常是Purchase ID)做提前聚合,保证1个关联键仅对应1条记录后再执行JOIN操作,从根源上避免行复制:

  • 若仅需要判断是否存在折扣:使用子查询提前按关联键去重
    LEFT JOIN (SELECT DISTINCT purchase_id FROM purchase_discount) pd 
    ON p.id = pd.purchase_id
    
  • 若需要统计折扣汇总数据:提前按关联键做聚合计算
    LEFT JOIN (
      SELECT 
        purchase_id,
        SUM(discount_amount) AS total_discount,
        COUNT(*) AS discount_count
      FROM purchase_discount 
      GROUP BY purchase_id
    ) pd ON p.id = pd.purchase_id
    

方案2:调整聚合与关联的执行顺序

先完成不需要依赖Purchase Discount的核心业务聚合,再关联折扣表获取相关字段,此时就算折扣表有多条匹配,也不会影响已经聚合完成的销售统计结果:

-- 更优写法:先聚合核心数据再关联折扣,完全避免冗余行影响统计
WITH core_sales AS (
  SELECT
    i.id AS item_id,
    ARRAY_AGG(pi.id) AS purchase_items_ids,
    COUNT(pi.id) AS total_sold,
    p.id AS purchase_id
  FROM item i
  INNER JOIN purchase_item pi ON i.id = pi.item_id
  INNER JOIN purchase p ON pi.purchase_id = p.id
  GROUP BY i.id, p.id
)
SELECT 
  cs.item_id,
  cs.purchase_items_ids,
  cs.total_sold
FROM core_sales cs
LEFT JOIN purchase_discount pd ON cs.purchase_id = pd.purchase_id
GROUP BY cs.item_id, cs.purchase_items_ids, cs.total_sold;

以上两种方案均是在关联阶段就避免了冗余行的生成,不需要对最终大结果集做全局去重,数据量级越大,性能优势越突出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 13:09:03