PostgreSQL关联聚合查询统计用户总支付金额结果错误
问题说明
现有两张业务数据表:
- 站点访问行为表 user_activity_log:存储用户访问站点的全量行为日志,字段包含
id、client_id、hitdatetime、action,示例数据:
| id | client_id | hitdatetime | action |
|---|---|---|---|
| 2661715 | 17 | 2020-09-18 11:30:43 | visit |
| 2661716 | 17 | 2020-09-18 11:30:54 | registration |
| 2661717 | 17 | 2020-09-18 11:31:16 | visit |
- 用户支付记录表 user_payment_log:存储用户支付全流程的行为日志,字段包含
id、client_id、hitdatetime、action、payment_amount,示例数据:
| id | client_id | hitdatetime | action | payment_amount |
|---|---|---|---|---|
| 1 | 30 | 2021-08-12 03:43:02.176 | open-paystation | 0.00 |
| 2 | 30 | 2021-08-12 03:43:02.665 | choose-method | 0.00 |
| 3 | 30 | 2021-08-12 03:43:07.463 | accept-method | 0.00 |
需求为关联两张表,计算每个用户全周期累计消费总金额,输出字段为total_payment_amount。
故障现象
最初编写的查询SQL如下:
SELECT user_activity_log.client_id, SUM(user_payment_log.payment_amount) as total_payment_amount FROM user_payment_log RIGHT JOIN user_activity_log ON user_activity_log.client_id = user_payment_log.client_id GROUP BY user_activity_log.client_id ORDER BY client_id;
执行后结果异常:client_id=3的用户计算得出的total_payment_amount为632.39,但核对该用户在支付表的全量记录,实际有效支付总金额仅为57.49,结果整整放大11倍,数值完全错误。该用户的支付明细如下:
| id | client_id | hitdatetime | action | payment_amount |
|---|---|---|---|---|
| 76 | 3 | 2021-08-11 03:18:09.978 | open-paystation | 0.00 |
| 77 | 3 | 2021-08-11 03:18:10.535 | choose-method | 0.00 |
| 78 | 3 | 2021-08-11 03:18:12.409 | accept-method | 0.00 |
| 79 | 3 | 2021-08-11 03:18:27.09 | make-payment | 57.49 |
| 80 | 3 | 2021-08-11 03:19:27.618 | open-paystation | 0.00 |
根因与修复
问题根因:直接RIGHT JOIN关联user_activity_log表时,该表中同一个client_id对应多条访问行为记录,关联阶段会产生笛卡尔积,单条支付记录会被重复匹配多次,后续SUM聚合时重复累加,最终导致计算结果偏大。
修复方案:先对user_activity_log表的client_id做去重,拿到全量唯一的用户ID集合后,再和支付表做关联聚合,修正后的SQL如下:
SELECT t.client_id, SUM(user_payment_log.payment_amount) as total_payment_amount FROM user_payment_log RIGHT JOIN ( SELECT DISTINCT client_id FROM user_activity_log) as t ON t.client_id = user_payment_log.client_id GROUP BY t.client_id
内容的提问来源于stack exchange,提问作者Roman Bolshevik
相关产品推荐
相关产品推荐

