MySQL使用UNION連接兩個查詢排序失效


概述

UNION

連接數據集關鍵字,可以將兩個查詢結果集拼接為一個,過濾掉相同的記錄

UNION ALL

連接數據集關鍵字,可以將兩個查詢結果集拼接為一個,不會過濾掉相同的記錄

今天在接到一個需求的時候使用了UNION進行查詢后發現,如果兩個查詢分別使用ORDER BY后拼接居然無法成功排序,經過了好一番折騰,記錄下

表結構及數據

-- 創建表
CREATE TABLE test_user (
  ID int(11) NOT NULL AUTO_INCREMENT,
  USER_ID int(11) DEFAULT NULL COMMENT '用戶賬號',
  USER_NAME varchar(255) DEFAULT NULL COMMENT '用戶名',
  AGE int(5) DEFAULT NULL COMMENT '年齡',
  COMMENT varchar(255) DEFAULT NULL COMMENT '簡介',
  PRIMARY KEY (ID)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- 數據插入語句
INSERT INTO test_user (ID, USER_ID, USER_NAME, AGE, COMMENT) VALUES ('1', '111', '開心菜鳥', '18', '今天很開心');
INSERT INTO test_user (ID, USER_ID, USER_NAME, AGE, COMMENT) VALUES ('2', '222', '悲傷菜鳥', '21', '今天很悲傷');
INSERT INTO test_user (ID, USER_ID, USER_NAME, AGE, COMMENT) VALUES ('3', '333', '認真菜鳥', '30', '今天很認真');
INSERT INTO test_user (ID, USER_ID, USER_NAME, AGE, COMMENT) VALUES ('4', '444', '高興菜鳥', '18', '今天很高興');
INSERT INTO test_user (ID, USER_ID, USER_NAME, AGE, COMMENT) VALUES ('5', '555', '嚴肅菜鳥', '21', '今天很嚴肅');

默認表數據顯示如下

ID USER_ID USER_NAME AGE COMMENT
1 111 開心菜鳥 18 今天很開心
2 222 悲傷菜鳥 21 今天很悲傷
3 333 認真菜鳥 30 今天很認真
4 444 高興菜鳥 18 今天很高興
5 555 嚴肅菜鳥 21 今天很嚴肅

運行結果分析

-- 查詢1
SELECT
	*
FROM
	test_user u
ORDER BY AGE

結果集1

ID USER_ID USER_NAME AGE COMMENT
1 111 開心菜鳥 18 今天很開心
4 444 高興菜鳥 18 今天很愉快
2 222 悲傷菜鳥 21 今天很悲傷
5 555 嚴肅菜鳥 21 今天很嚴肅
3 333 認真菜鳥 30 今天很認真
-- 查詢2
-- 使用UNION
(
    SELECT
    	*
    FROM
    	test_user u
    ORDER BY AGE
)
UNION
(
    SELECT
    	*
    FROM
    	test_user u
    ORDER BY AGE
);

-- 查詢3
-- 使用UNION ALL
(
    SELECT
    	*
    FROM
    	test_user u
    ORDER BY AGE
)
UNION ALL
(
    SELECT
    	*
    FROM
    	test_user u
    ORDER BY AGE
)

結果集2使用UNION

由於UNION會合並相同的記錄(與DISTINCT實現相同效果),因此此處顯示僅有5條記錄

ID USER_ID USER_NAME AGE COMMENT
1 111 開心菜鳥 18 今天很開心
2 222 悲傷菜鳥 21 今天很悲傷
3 333 認真菜鳥 30 今天很認真
4 444 高興菜鳥 18 今天很高興
5 555 嚴肅菜鳥 21 今天很嚴肅

結果集3使用UNION ALL

ID USER_ID USER_NAME AGE COMMENT
1 111 開心菜鳥 18 今天很開心
2 222 悲傷菜鳥 21 今天很悲傷
3 333 認真菜鳥 30 今天很認真
4 444 高興菜鳥 18 今天很高興
5 555 嚴肅菜鳥 21 今天很嚴肅
1 111 開心菜鳥 18 今天很開心
2 222 悲傷菜鳥 21 今天很悲傷
3 333 認真菜鳥 30 今天很認真
4 444 高興菜鳥 18 今天很高興
5 555 嚴肅菜鳥 21 今天很嚴肅

如果需要使用UNION ALL又需要進行排序,則要將其作為一個子查詢來查

-- 查詢4
-- 將UNION ALL作為子查詢並進行排序
SELECT
	*
FROM
	(
		(
			SELECT
				*
			FROM
				test_user u
			ORDER BY
				AGE
		)
		UNION ALL
		(
			SELECT
				*
			FROM
				test_user u
			ORDER BY
				AGE
		)
	) a
ORDER BY
	AGE;

結果集4

ID USER_ID USER_NAME AGE COMMENT
1 111 開心菜鳥 18 今天很開心
4 444 高興菜鳥 18 今天很愉快
1 111 開心菜鳥 18 今天很開心
4 444 高興菜鳥 18 今天很愉快
2 222 悲傷菜鳥 21 今天很悲傷
5 555 嚴肅菜鳥 21 今天很嚴肅
2 222 悲傷菜鳥 21 今天很悲傷
5 555 嚴肅菜鳥 21 今天很嚴肅
3 333 認真菜鳥 30 今天很認真
3 333 認真菜鳥 30 今天很認真

 改進

在經過一番搜索相關的經驗后發現,是我之前有些畫蛇添足了,原來可以在不使用子查詢即可完成排序的方法:

-- 查詢5
-- 第一個查詢不使用排序,如果使用的話不加括號會報錯(這也是我之前為什么會想用子查詢的原因而沒有想過這種方式了)
SELECT
	*
FROM
	test_user u

UNION ALL

SELECT
	*
FROM
	test_user u
ORDER BY
	AGE

運行出來的結果集與結果集4是相同的,此處就不再粘出結果。

結論

當我們使用UNION(或者UNION ALL)語句時,如果UNION的兩個結果集在單獨排序后再拼接,則他們的ORDER BY是失效的。如果我們要進行排序有以下兩種方法:

  1. 將它們作為子查詢再ORDER BY查詢一次(還是建議使用方法2,子查詢太不簡潔了)
  2. 在第一個結果集中不使用排序,且不用括號分隔,而在第二個結果集后使用ORDER BY

參考鏈接

cnblogs:MySQL中UNION和UNION ALL的使用

才疏學淺,如文中有錯誤,感謝大家指出。  


免責聲明!

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



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