MYSQL之union和order by分析([Err] 1221 - Incorrect usage of UNION and ORDER BY)


我在一個業務中采用了按月的分表策略,當查詢的條件跨月的時候,使用了union all匯總2個表的數據,並按插入時間倒序排列。查詢並不復雜,但是當執行的時候卻報錯了。

 

[sql] view plain copy
 
  1. SELECT * FROM `table_201604` ORDER BY `REPORT_TIME` DESC  
  2. UNION ALL  
  3. SELECT * FROM `table_201605` ORDER BY `REPORT_TIME` DESC  
  4.   
  5. [Err] 1221 - Incorrect usage of UNION and ORDER BY  

 

報錯的原因,是不正確使用UNION和ORDER BY指令,為什么呢?經過一番查找資料,才知道MYSQL中UNION的語法是這樣子的

 

[sql] view plain copy
 
  1. substatement union [all] substatement union [all] substatement [order by-clause] [limit-clause]  


注意:

 

1. 每一個子句可以使用()包圍,但是當第一個子句使用了()時,其它的子句都必須使用括號包圍。

2. 每一個字句可以包含WHERE,GROUP BY,HAVING,JOIN,LIMIT,但是不能使用ORDER BY,如果需要使用ORDER BY,必須使用()包圍子句。

接下來,做一些實驗,能更好地理解,創建表和數據的SQL語句如下:

 

[sql] view plain copy
 
  1. CREATE TABLE `union_a` (  
  2.   `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',  
  3.   `T_NAME` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT ''COMMENT '所在表名稱',  
  4.   `NUMBER` int(11) NOT NULL DEFAULT '0' COMMENT '用於排序',  
  5.   PRIMARY KEY (`ID`)  
  6. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;  
  7. CREATE TABLE `union_b` LIKE `union_a`;  
  8. INSERT INTO `union_a` VALUES ('1', 'a', '100');  
  9. INSERT INTO `union_a` VALUES ('2', 'a', '28');  
  10. INSERT INTO `union_a` VALUES ('3', 'a', '98');  
  11. INSERT INTO `union_a` VALUES ('4', 'a', '19');  
  12. INSERT INTO `union_a` VALUES ('5', 'a', '999');  
  13. INSERT INTO `union_b` VALUES ('1', 'b', '23');  
  14. INSERT INTO `union_b` VALUES ('2', 'b', '76');  
  15. INSERT INTO `union_b` VALUES ('3', 'b', '32');  
  16. INSERT INTO `union_b` VALUES ('4', 'b', '43');  
  17. INSERT INTO `union_b` VALUES ('5', 'b', '11');  

 

一、關於LIMIT

執行以下SQL語句

 

[sql] view plain copy
 
  1. SELECT * FROM `union_a` LIMIT 1  
  2. UNION ALL  
  3. SELECT * FROM `union_b` LIMIT 1  

可能第一眼看到這個SQL的時候,會想到將會返回2條記錄,但是,結果卻是只返回1條記錄。回憶UNION的語法,最后一個LIMIT 1其實是對UNION之后的結果集取1條記錄。

 

二、關於ORDER BY

我的需求是這樣的,`union_a`和`union_b`表按NUMBER字段升序排列,最后將2個結果集合並,你可能想到的SQL會是這個樣子

 

[sql] view plain copy
 
  1. SELECT * FROM `union_a` ORDER BY `NUMBER`  
  2. UNION ALL  
  3. SELECT * FROM `union_b` ORDER BY `NUMBER`  

前面也說過,這個SQL語句是有語法錯誤的,但是,可以嘗試這樣,使用()將每個子句包圍

 

 

[sql] view plain copy
 
  1. (SELECT * FROM `union_a` ORDER BY `NUMBER`)  
  2. UNION ALL  
  3. (SELECT * FROM `union_b` ORDER BY `NUMBER`)  

SQL語句順利執行了,但是,結果卻不是我們想要的。看前5條記錄,`union_a`表中的數據並沒有按照NUMBER字段升序排列

查閱MYSQL的官方文檔,其中包含對UNION中使用ORDER BY的說明:

 

對UNION中的子句應用ORDER BY是無效的,ORDER BY只能用於UNION后的整個結果集。如果需要對子句應用ORDER BY,必須添加LIMIT。正確的SQL如下

 

[sql] view plain copy
 
  1. (SELECT * FROM `union_a`  ORDER BY `NUMBER` LIMIT 5)  
  2. UNION ALL  
  3. (SELECT * FROM `union_b` ORDER BY `NUMBER` LIMIT 5)  

 

參考鏈接:

https://dev.mysql.com/doc/refman/5.7/en/union.html

http://stackoverflow.com/questions/6732661/incorrect-usage-of-union-and-order-by


免責聲明!

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



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