久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySql Group by函數怎么正確使用

229次閱讀
沒有評論

共計 2188 個字符,預計需要花費 6 分鐘才能閱讀完成。

這篇文章主要介紹了 MySql Group by 函數怎么正確使用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇 MySql Group by 函數怎么正確使用文章都會有所收獲,下面我們一起來看看吧。

MySql Group by 函數的正確打開方式

在使用分組函數時, 進行結果集篩選, 遇到的一些問題以及解決辦法

1. 應用場景

有兩張表

文章表 (一對多留言表) t_posts:      
oid, posts_name    
留言表(多對一文章表) t_comment:    
oid, posts_id, msg_content, create_time

2. 需求分析

查詢每個文章的最新回復內容

3.SQL 編寫

select 
 tp.oid,
 tp.posts_name,
 tc.msg_content,
 tc.create_time
from t_posts tp 
left join t_comment tc on tp.oid = tc.posts_id
group by tp.oid having create_time = max(create_time)

假設現在有兩個文章 A, B (回復的記錄在數據庫的順序與下述一致)

A 有一個回復記錄時間為: 2019-09-10  
A 有一個回復記錄時間為: 2019-09-11  
B 有一個回復記錄時間為: 2019-09-01  
B 有一個回復記錄時間為: 2019-09-09

運行上面的 sql, 會發現結果集丟失大量記錄, 并且結果是錯誤的, 經過查詢資料得知

mysql 的 having 是在 group by 之后再執行, 也就是說, 先分組, 在過濾, 但是因為存在兩條以上的留言記錄,
所以分組之后的結果集只會取每條留言的第一條作為分組之后的記錄信息, 這時如果使用 having create_time = max(create_time)
那么, max(create_time) 為當前分組的最大時間

為: 2019-09-10 和 2019-09-09

所以上述 sql 會丟失結果集

4. 改造 SQL

因為知道分組之后合并的重復結果集為 rownum 最小的那條, 那么可不可以改造 sql 如下??

select 
 tp.oid,
 tp.posts_name,
 tc.msg_content,
 tc.create_time
from t_posts tp 
left join t_comment tc on tp.oid = tc.posts_id
group by tp.oid having create_time = max(create_time)
--  下面的是新增的 sql
order by tc.create_time desc

運行之后發現依舊不好使, 證明 order by 在 group by having 之后

后來想想可不可以 不用 having, 直接用 order by 來優化分組后的結果呢?

having create_time = max(create_time)

select 
 tp.oid,
 tp.posts_name,
 tc.msg_content,
 tc.create_time
from t_posts tp 
left join t_comment tc on tp.oid = tc.posts_id
group by tp.oid 
order by tc.create_time desc

結果集錯誤, 并不能影響分組結果, 依舊是按照 rownum 最小分組合并重復結果集, 然后在排序

5. 終極改造版本

因為 order by 只能后影響 group by, 那么是不是可以在 group by 之前先把結果集排序一下, 然后再分組呢?

select * from (
 select 
 tp.oid,
 tp.posts_name,
 tc.msg_content,
 tc.create_time
 from t_posts tp 
 left join t_comment tc on tp.oid = tc.posts_id
 order by tc.create_time desc
) t 
group by t.oid

發現還是不好使, 但是子查詢確實先排序了

經查詢(explain), 發現子查詢的 order by 被優化沒了, 解決辦法:

在子查詢里使用 limit 99999

在子查詢里使用 where 條件, create_time = (select max(create_time) from t_comment group by oid)

select * from (
 select 
 tp.oid,
 tp.posts_name,
 tc.msg_content,
 tc.create_time
 from t_posts tp 
 left join t_comment tc on tp.oid = tc.posts_id
 order by tc.create_time desc limit 9999
) t 
group by t.oid

大功告成

附加知識點:

mysql5.5 與 mysql 5.7 版本差異: 5.7+ 版本, 如果不使用 limit, group by 會把 order by 優化掉

關于“MySql Group by 函數怎么正確使用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“MySql Group by 函數怎么正確使用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-15發表,共計2188字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 舞钢市| 湖州市| 永寿县| 神农架林区| 安远县| 都江堰市| 陈巴尔虎旗| 宜君县| 含山县| 双鸭山市| 上饶市| 灯塔市| 洪雅县| 新昌县| 新郑市| 卓资县| 崇州市| 观塘区| 余江县| 自贡市| 桃园县| 漾濞| 金寨县| 郯城县| 湘阴县| 酉阳| 新沂市| 卓资县| 迁安市| 闵行区| 青龙| 合水县| 谢通门县| 洛浦县| 邢台县| 兴义市| 竹溪县| 浦东新区| 特克斯县| 花莲县| 舞钢市|