Postgres多表关联查询去重 避免重复计数统计项目用户数
数据库表结构
涉及的核心数据表字段如下:
| user表 | learning_group(学习组)表 | program(项目)表 | learning_group_user(学习组-用户关联)表 | learning_group_program(学习组-项目关联)表 |
|---|---|---|---|---|
| id | id | id | id | id |
| name | name | name | learning_group_id | learning_group_id |
| user_id | program_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
相关产品推荐
相关产品推荐

