前言
今天同事在同步完订单数据后,由于订单总金额和数据源的总金额存在差异,选择使用LIMIT和SUM()函数计算当前分页的总金额来和对方比较特定订单的总金额,却发现计算出来的金额并不是分页的订单总金额,而是所有订单的总金额。
数据库版本为mysql 5.7,下面会用一个示例复盘遇到的问题。
问题复盘
本次复盘会用一个很简单的订单表作为示例。
数据准备
订单表建表语句如下(这里偷懒了,使用了自增ID,实际开发中不建议使用自增ID作为订单ID)
CREATE TABLE `order` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单ID', `amount` decimal(10,2) NOT NULL COMMENT '订单金额', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
插入金额为100的SQL如下(执行10次即可)
INSERT INTO `order`(`amount`) VALUES (100);
所以总金额为10*100=1000。
问题SQL
使用limit对数据进行分页查询,同时使用sum()函数计算出当前分页的总金额
SELECT SUM(`amount`) FROM `order` ORDER BY `id` LIMIT 5;
前面也提到了运行的结果,期待的结果应该为5*100=500,然而实际运行的结果却为1000.00(带有小数点是因为数据类型)
问题排查
其实如果对SELECT语句执行顺序有一定了解的朋友可以很快确定为什么返回的结果为所有的订单总金额?下面我会就问题SQL的执行书序来分析问题:
- FROM:FROM子句是最先执行的,确定了查询的是order这张表
- SELECT:SELECT子句是第二个执行的子句,同时SUM()函数也在此时执行了。
- ORDER BY:ORDER BY子句是第三个执行的子句,其处理的结果只有一个,就是订单总金额
- LIMIT:LIMIT子句是最后执行的,此时结果集中只有一个结果(订单总金额)
补充内容
这里补充一下SELECT语句执行顺序
- FROM <left_table>
- ON <join_condition>
- <join_type> JOIN <right_table>
- WHERE <where_condition>
- GROUP BY <group_by_list>
- HAVING <having_condition>
- SELECT
- DISTINCT <select_list>
- ORDER BY <order_by_condition>
- LIMIT <limit_number>
解决办法
遇到需要统计分页数据时(除了SUM()函数外,常见的COUNT()、AVG()、MAX()、MIN()函数也存在这个问题),可以选择使用子查询来处理(PS:这里不考虑内存计算,针对的是使用数据库解决这个问题)。上面的问题解决方案如下:
SELECT SUM(o.amount) FROM (SELECT `amount` FROM `order` ORDER BY `id` LIMIT 5) AS o;
运行的返回值为500.00。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。