mysql join sum時數據重復問題及解決方案


當我們使用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

 

結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM