欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mysql分組查詢每組最新一條數(shù)據(jù)的三種實(shí)現(xiàn)方法

 更新時(shí)間:2023年01月12日 11:07:32   作者:kerwin_code  
我們?cè)陂_發(fā)中經(jīng)常會(huì)遇到分組查詢最新數(shù)據(jù)的問題,下面這篇文章主要給大家介紹了關(guān)于Mysql分組查詢每組最新一條數(shù)據(jù)的三種實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在寫報(bào)表功能時(shí)遇到一個(gè)需要根據(jù)用戶id分組查詢最新一條錢包明細(xì)數(shù)據(jù)的需求,在寫sql測(cè)試時(shí)遇到一個(gè)有趣的問題,開始使用子查詢根據(jù)時(shí)間倒序+group by customer_id發(fā)現(xiàn)查詢出來(lái)的數(shù)據(jù)一直都是最舊的一條,而不是我需要的最新一條數(shù)據(jù)我明明已經(jīng)倒序排了,后來(lái)總結(jié)出了三種解決方案如下。

注意事項(xiàng)

  • 數(shù)據(jù)庫(kù)版本 Mysql5.7+
  • 執(zhí)行 GROUP BY 語(yǔ)句的時(shí)候出現(xiàn) sql_mode=only_full_group_by 解決方法(這里是Mysql8的解決方案,Mysql5.7也差不多自行百度即可)

1、執(zhí)行 select @@sql_mode; 查看sql模式

select @@sql_mode;

2、將sql_mode中的only_full_group_by模式剔除 重新設(shè)置sql_mode值,如果是使用JDBC連接需要重啟項(xiàng)目才能生效。

set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

準(zhǔn)備SQL

這里模擬一個(gè)sql

DROP TABLE IF EXISTS `customer_wallet_detail`;
CREATE TABLE `customer_wallet_detail`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `customer_id` bigint(20) NULL DEFAULT NULL COMMENT '用戶ID',
  `happen_amount` varchar(15)  NULL DEFAULT '0' COMMENT '發(fā)生金額 帶'-'號(hào)的代表扣款',
  `balance_amount` varchar(15) NULL DEFAULT '0' COMMENT '可用余額',
  `create_time` bigint(20) NULL DEFAULT NULL COMMENT '發(fā)生時(shí)間',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '用戶錢包明細(xì)' ;

INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (1, 1, '100', '100', 1670300656630);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (2, 1, '-10', '90', 1670300656640);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (3, 1, '5', '95', 1670300656650);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (4, 3, '998', '998', 1670300656660);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (5, 3, '-100', '898', 1670300656670);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (6, 3, '-98', '800', 1670300656680);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (7, 2, '666', '666', 1670300656690);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (8, 2, '-66', '600', 1670300656695);
INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (9, 2, '-600', '0', 1670300656699);

錯(cuò)誤查詢

SELECT
	* 
FROM
	( SELECT * FROM customer_wallet_detail ORDER BY create_time DESC ) t1 
GROUP BY
	t1.customer_id;

錯(cuò)誤原因

在mysql5.7以及之后的版本,如果GROUP BY的子查詢中包含ORDER BY,但是 GROUP BY 不與 LIMIT 配合使用,ORDER BY會(huì)被忽略掉,所以子查詢?cè)?GROUP BY 時(shí)排序不會(huì)生效,可能是因?yàn)樽硬樵兇蠖鄶?shù)是作為一個(gè)結(jié)果給主查詢使用,所以子查詢不需要排序。

方法一

鑒于以上的原因我們可以添加上 LIMIT 條件來(lái)實(shí)現(xiàn)功能。

PS:這個(gè)LIMIT的數(shù)量可以先自行 COUNT 出你要遍歷的數(shù)據(jù)條數(shù)(這個(gè)數(shù)據(jù)條數(shù)是所有滿足查詢條件的數(shù)據(jù)合,我這里共9條數(shù)據(jù))

SELECT
	* 
FROM
	( SELECT * FROM customer_wallet_detail ORDER BY create_time DESC ) t1 
GROUP BY
	t1.customer_id;

方法二(適用于自增ID和創(chuàng)建時(shí)間排序一致)

方法一需要先 COUNT 查詢?nèi)缓髮⒉樵兘Y(jié)果設(shè)置到 LIMIT 條件中比較麻煩,這里還可以使用 MAX() 函數(shù)來(lái)實(shí)現(xiàn)該功能。

PS:因?yàn)槲疫@里的業(yè)務(wù)數(shù)據(jù)是有序插入的,使用主鍵自增id和create_time結(jié)果是一樣的而且使用id查詢效率更高,如果沒有唯一且有序的id可以替代create_time那么就用方案一,不能直接使用 SELECT id,MAX(create_time) 這種操作來(lái)獲取最新一條數(shù)據(jù)id原因在總結(jié)中有詳細(xì)描述。

SELECT
	*
FROM
	customer_wallet_detail 
WHERE
	id IN ( SELECT MAX( id ) FROM customer_wallet_detail GROUP BY customer_id ) 
ORDER BY
	customer_id;

方法三(適用于自增ID和創(chuàng)建時(shí)間排序一致)

方法三和方法二實(shí)現(xiàn)邏輯基本一致只是將IN查詢替換成了連接查詢,本地20w條數(shù)據(jù)測(cè)試 方法三比方法二性能提升50%,有興趣的可以增大數(shù)據(jù)集測(cè)試后續(xù)性能變化。

SELECT
	t1.* 
FROM
	customer_wallet_detail t1
	INNER JOIN ( SELECT MAX( id ) AS id FROM customer_wallet_detail GROUP BY customer_id ) t2 ON t1.id = t2.id

總結(jié)

結(jié)合我的業(yè)務(wù)經(jīng)過(guò)測(cè)試,目前看來(lái)方案三是最合適的,sql簡(jiǎn)單性能適中,方案一比方案二性能更差而且實(shí)現(xiàn)麻煩,最終選擇那個(gè)方案主要看業(yè)務(wù)而定。

MAX()函數(shù)和MIN()這一類函數(shù)和GROUP BY配合使用存在問題

MAX()函數(shù)和MIN()這一類函數(shù)和GROUP BY配合使用,GROUP BY拿到的數(shù)據(jù)永遠(yuǎn)都是這個(gè)分組排序最上面的一條,而MAX()函數(shù)和MIN()這一類函數(shù)會(huì)將這個(gè)分組中最大 | 最小的值取出來(lái),這樣會(huì)導(dǎo)致查詢出來(lái)的數(shù)據(jù)對(duì)應(yīng)不上。

正確查詢:

錯(cuò)誤查詢:這里的確拿到每個(gè)分組最新創(chuàng)建時(shí)間了但是拿的數(shù)據(jù)id還是排序的第一條

到此這篇關(guān)于Mysql分組查詢每組最新一條數(shù)據(jù)的三種實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)Mysql分組查詢每組最新數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mysql表的清空、刪除和修改操作詳解

    mysql表的清空、刪除和修改操作詳解

    這篇文章主要詳細(xì)介紹了mysql表的清空、刪除和修改操作的方法,以及一些常用的mysql的常用操作,非常的簡(jiǎn)單實(shí)用,有需要的可以參考下
    2014-09-09
  • Mysql如何巧妙的繞過(guò)未知字段名詳解

    Mysql如何巧妙的繞過(guò)未知字段名詳解

    這篇文章主要給大家介紹了Mysql如何巧妙的繞過(guò)未知字段名的相關(guān)資料,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),對(duì)學(xué)習(xí)mysql具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-05-05
  • Mysql?DateTime?查詢問題解析

    Mysql?DateTime?查詢問題解析

    這篇文章主要為大家介紹了Mysql?DateTime查詢問題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • MySql超長(zhǎng)自動(dòng)截?cái)鄬?shí)例詳解

    MySql超長(zhǎng)自動(dòng)截?cái)鄬?shí)例詳解

    這篇文章主要介紹了MySql超長(zhǎng)自動(dòng)截?cái)鄬?shí)例詳解的相關(guān)資料,這里通過(guò)實(shí)例來(lái)說(shuō)明如何實(shí)現(xiàn)自動(dòng)截?cái)嗟墓δ?,需要的朋友可以參考?/div> 2017-07-07
  • mysql workbench 設(shè)置外鍵的方法實(shí)現(xiàn)

    mysql workbench 設(shè)置外鍵的方法實(shí)現(xiàn)

    在MySQL Workbench中設(shè)置外鍵屬性是非常方便的,本文就來(lái)介紹一下mysql workbench 設(shè)置外鍵的方法實(shí)現(xiàn),具有一定能的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • MySql學(xué)習(xí)筆記之事務(wù)隔離級(jí)別詳解

    MySql學(xué)習(xí)筆記之事務(wù)隔離級(jí)別詳解

    這篇文章主要給大家介紹了關(guān)于MySql學(xué)習(xí)筆記之事務(wù)隔離級(jí)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • CentOS7.x?安裝mysql5.7?XtraBackUp備份工具使用命令詳解

    CentOS7.x?安裝mysql5.7?XtraBackUp備份工具使用命令詳解

    這篇文章主要介紹了CentOS7.x?安裝mysql5.7?XtraBackUp備份工具使用,本文給大家介紹了mysql安裝過(guò)程及命令使用方法,需要的朋友可以參考下
    2022-04-04
  • 解決mysql刪除用戶 bug的問題

    解決mysql刪除用戶 bug的問題

    這篇文章主要介紹了解決mysql刪除用戶 bug的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • MySQL數(shù)據(jù)庫(kù)開啟、關(guān)閉、查看函數(shù)功能的方法

    MySQL數(shù)據(jù)庫(kù)開啟、關(guān)閉、查看函數(shù)功能的方法

    這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)開啟、關(guān)閉、查看函數(shù)功能的方法,本文為解決一個(gè)錯(cuò)誤總結(jié)而來(lái),錯(cuò)誤信息本文一同給出,需要的朋友可以參考下
    2014-10-10
  • MySQL外鍵使用及說(shuō)明詳解

    MySQL外鍵使用及說(shuō)明詳解

    MySQL通過(guò)外鍵約束來(lái)保證表與表之間的數(shù)據(jù)的完整性和準(zhǔn)確性。這篇文章還通過(guò)外鍵的使用條件和外鍵的好處定義語(yǔ)法方面介紹了mysql外鍵使用及說(shuō)明,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友一起看下吧
    2016-08-08

最新評(píng)論