今天同事在同步完訂單數據後,因爲訂單總金額和數據源的總金額存在差別,選擇使用LIMIT
和SUM()
函數計算當前分頁的總金額來和對方比較特定訂單的總金額,卻發現計算出來的金額並非分頁的訂單總金額,而是全部訂單的總金額。mysql
數據庫版本爲mysql 5.7
,下面會用一個示例覆盤遇到的問題。sql
本次覆盤會用一個很簡單的訂單表做爲示例。數據庫
訂單表建表語句以下(這裏偷懶了,使用了自增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
次便可)code
INSERT INTO `order`(`amount`) VALUES (100);
因此總金額爲10*100=1000
。內存
使用limit
對數據進行分頁查詢,同時使用sum()
函數計算出當前分頁的總金額ci
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
語句執行順序it
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
。