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

Postgres多表关联查询去重 避免重复计数统计项目用户数

数据库表结构

涉及的核心数据表字段如下:

user表learning_group(学习组)表program(项目)表learning_group_user(学习组-用户关联)表learning_group_program(学习组-项目关联)表
ididididid
namenamenamelearning_group_idlearning_group_id
user_idprogram_id
业务规则与需求
  • 权限关联逻辑:用户通过加入学习组获得项目权限,当用户归属某学习组、且目标项目也分配给该学习组时,用户即拥有该项目的完成权限
  • 多对多规则:单个用户可加入多个学习组,单个项目也可分配给多个学习组
  • 统计要求:统计指定项目的可参与用户总数时,同一用户即使通过多个学习组和该项目产生关联,也只能计数1次,不得重复统计

示例:用户John Smith加入了3个学习组,"Science Program"项目同时分配给了这3个学习组,统计该项目用户数时,John仅计1次,不能按3条关联记录计3次。

初始问题SQL

最初采用子查询实现项目信息+用户数的联查,语句如下,但存在重复计数问题:

SELECT 
  p.id, 
  p.data, 
  (
    SELECT count(u.id)
    FROM learning_group_user lgu
    INNER JOIN learning_group_program lgp ON lgp.learning_group_id = lgu.learning_group_id
    INNER JOIN program p ON p.id = lgp.program_id
    INNER JOIN user u ON u.id = lgu.user_id
    WHERE lgp.program_id = 'e4b284da-c94b-4546-84b9-2616e6a32b53'
  ) program_learners_count 
FROM program p
WHERE p.id = 'e4b284da-c94b-4546-84b9-2616e6a32b53';

问题原因:子查询直接count用户ID,没有对多学习组关联产生的重复用户记录做去重,导致统计值偏大。

最终可用方案

通过count(distinct 用户ID)的方式对关联结果去重,即可得到符合要求的统计值,调整后可正常运行的SQL如下:

SELECT 
    p.*,
    (
        SELECT count(distinct lgl.user_id)
        FROM learning_group_learner lgl
            INNER JOIN learning_group_program lgp 
            ON lgp.learning_group_id = lgl.learning_group_id
        WHERE lgp.program_id = '3772c437-f881-4a69-b846-544d1783b1a4'
    )
FROM program p
WHERE p.id = '3772c437-f881-4a69-b846-544d1783b1a4';

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:57:26