ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql sum 重复计算_mysql join sum时数据重复问题及解决方案

2021-08-03 16:33:37  阅读:228  来源: 互联网

标签:10 uid 重复 sum amount user mysql ub


当我们使用mysql的join功能从多张表中取出数据并使用sum分别对取出的数据求和时

会发现sum出来的值是不对的,往往是正确值的整数倍

为什么会出现这样的情况呢

复现

假设有两张表:user_buy 和user_sell,分别记录了用户在某天的购买和出售金额,

结构如下:

CREATE TABLE `user_buy` (

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,

`uid` int(10) unsigned NOT NULL COMMENT '用户id',

`amount` int(10) unsigned default '0' COMMENT '数量',

`init_time` date not null comment '日期',

PRIMARY KEY (`id`),

KEY `uid` (`uid`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户购买统计';

CREATE TABLE `user_sell` (

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,

`uid` int(10) unsigned NOT NULL COMMENT '用户id',

`amount` int(10) unsigned default '0' COMMENT '数量',

`init_time` date not null comment '日期',

PRIMARY KEY (`id`),

KEY `uid` (`uid`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户出售统计';

数据如下:

 

 

 

 

现在我想求用户在一段时间里面的购买总金额 - 出售总金额,并根据差值排序,取前30个用户

一番思考后,我写下了如下sql

SELECT
    ub.uid,
    sum( ub.amount ) - sum( us.amount ) total 
FROM
    user_buy ub
    LEFT JOIN user_sell us ON ub.uid = us.uid 
GROUP BY
    ub.uid 
ORDER BY
    total 
    LIMIT 30

得到如下结果:

 

 

 

很明显,这个结果是不对的

用户11的正确值应该是(100+200) - (10 + 20) = 270

用户22的正确值应该是(300+400) -(30 + 40) = 630

sql得出的结果是正确值的2倍!

猜想

由于按照uid字段进行聚合,且uid也是两个表关联的联结字段,因此会出现以下情况:

1.user_buy中的某个uid在user_sell中存在,且在user_sell中有n条记录时,会使得sum(ub.amount)的值变为正常值的n倍

2.user_sell中的某个uid在user_buy中存在,且在user_buy中有m条记录时,会使得sum(us.amount)的值变为正常值的m倍

验证

修改数据,在user_sell中增加一条uid = 11的数据

 

 继续用上面的sql查询:

 

 

用户11的正确值应该是(100+200) - (10 + 20+30) = 240

780 怎么来的?

(100+200)* 3 - (10 + 20 +30)* 2 = 780

1260同理,猜想正确

解决方案

为了避免联表字段同时满足多条记录的情况

先用子查询在各自表中完成数据的聚合,将数据存放在临时表中,再联合临时表

此时两个临时表中的数据对聚合字段uid来说都是唯一的

sql如下:

SELECT
    ub.uid,
    sum( ub.amount ) - sum( us.amount ) total 
FROM
    ( SELECT uid, sum( amount ) AS amount FROM user_buy GROUP BY uid ) AS ub
    LEFT JOIN ( SELECT uid, sum( amount ) AS amount FROM user_sell GROUP BY uid ) AS us ON ub.uid = us.uid 
GROUP BY
    ub.uid 
ORDER BY
    total 
    LIMIT 30

结果:

 

标签:10,uid,重复,sum,amount,user,mysql,ub
来源: https://www.cnblogs.com/shisanye/p/15094870.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有