開發中經常會遇到,分組查詢最新數據的問題,比如下面這張表(查詢每個地址最新的一條記錄):
sql如下:
-- ---------------------------- -- Table structure for test -- ---------------------------- DROP TABLE IF EXISTS `test`; CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `address` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `create_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of test -- ---------------------------- INSERT INTO `test` VALUES (1, '張三1', '北京', '2019-09-10 11:22:23'); INSERT INTO `test` VALUES (2, '張三2', '北京', '2019-09-10 12:22:23'); INSERT INTO `test` VALUES (3, '張三3', '北京', '2019-09-05 12:22:23'); INSERT INTO `test` VALUES (4, '張三4', '北京', '2019-09-06 12:22:23'); INSERT INTO `test` VALUES (5, '李四1', '上海', '2019-09-06 12:22:23'); INSERT INTO `test` VALUES (6, '李四2', '上海', '2019-09-07 12:22:23'); INSERT INTO `test` VALUES (7, '李四3', '上海', '2019-09-11 12:22:23'); INSERT INTO `test` VALUES (8, '李四4', '上海', '2019-09-12 12:22:23'); INSERT INTO `test` VALUES (9, '王二1', '廣州', '2019-09-03 12:22:23'); INSERT INTO `test` VALUES (10, '王二2', '廣州', '2019-09-04 12:22:23'); INSERT INTO `test` VALUES (11, '王二3', '廣州', '2019-09-05 12:22:23');
平常我們會進行按照時間倒敘排列然后進行分組,獲取每個地址的最新記錄,sql如下:
SELECT * FROM(SELECT * FROM test ORDER BY create_time DESC) a GROUP BY address
但是查詢結果卻不是我們想要的:
執行時間按倒敘排列結果為:
所以真正想要得到的結果是id為2/8/11的記錄,上面的查詢得到的卻是1/5/9,這是為什么呢?
因為在mysql5.7的時候,子查詢的排序已經變為無效了,可能是因為子查詢大多數是作為一個結果給主查詢使用,所以子查詢不需要排序的原因。
那么我們應該怎么查呢,有兩種方式:
第一種:
SELECT * FROM(SELECT * FROM test ORDER BY create_time DESC LIMIT 10000) a GROUP BY address
結果為:
對子查詢的排序進行limit限制,此時子查詢就不光是排序,所以此時排序會生效,但是限制條數卻只能盡可能的設置大些
第二種:
SELECT t.* FROM (SELECT address,max(create_time) as create_time FROM test GROUP BY address) a LEFT JOIN test t ON t.address=a.address and t.create_time=a.create_time
通過MAX函數獲取最新的時間和地址(因為需要按照地址分組),然后作為一張表和原來的數據進行聯查,
條件就是地址和時間要和獲取的最大時間和地址相等,此時結果為:
這兩種方式的查詢效率差不太多,第二種比第一種查詢稍微快一點,可能是由於第二種方式的子查詢只有兩個字段(時間,被分組字段)的緣故吧!
感興趣的可以照一張字段多的數據量大的表查詢一下比較比較。
PS:第二種方式中最新的記錄,不能同時地點和時間都相同,如果出現這種情況,第二種方式會查出把這兩條記錄都查出來,而第一條不會。
所以根據業務和數據情況來選擇其中一種方式,畢竟效率差不太多。