昨天运营提了个需求,要拉下每个玩家在前天一天内的消耗钻石数量,想着很简单,就是根据玩家id group by分组下,然后用sum函数求和就好了。因为涉及到公司隐私,故将钻石消耗表简化为如下的结构
sql语句也就很简单了,如下所示。
select sum(consume_num) as total_consume,role_id,server_id from gold_consume where timestamp>=开始时间 and timestamp<=结束时间 group by role_id;
结果奇怪的事情出现了,不仅total_consume出现了奇怪的数字,还有很多role_id和server_id为空,但total_consume有值的情况,截图如下。
先是怀疑记的日志里可能存在role_id或者server_id为空的,于是去掉sum来试试,发现并没有出现空的情况,sql如下。
select consume_num as total_consume,role_id,server_id from gold_consume where timestamp>=开始时间 and timestamp<=结束时间 group by role_id;
接着怀疑是不是存在一个role_id对应多个server_id的情况,于是改group by role_id,server_id,再执行一次,查看结果,发现问题并没有解决,sql如下。
select sum(consume_num) as total_consume,role_id,server_id from gold_consume where timestamp>=开始时间 and timestamp<=结束时间 group by role_id,server_id;
最后仔细看了下表结构,猜想是不是因为consume_num的字段类型是varchar,不是数字,记日志的时候多了些空格造成的?于是尝试给consume_num强转为int试试,sql如下。
select sum(cast(consume_num as DECIMAL)) as total_consume,role_id,server_id from gold_consume where timestamp>=开始时间 and timestamp<=结束时间 group by role_id;
执行后发现问题得到解决,无奈脸~
后面也谷歌了这个问题,想知道下是什么原因,但看了一圈,也没找到很清晰能说服自己的理论(只找到一个说是mysql sum的时候对数据量小的时候是可以隐式转化成int求和的,但数据量大了,就不一定了)心塞。所以如果有哪位大佬知道这个问题的原理的,求赐教,跪谢。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。