問題
如何把數據按照某一個字段排重保留我們要的哪行記錄,然后以我們想要的順序排序好以后,查詢出來?
今天花了一整天的時間搞這個問題,本來以為是很簡單的問題就小瞧它了,結果發現網上一大堆錯誤答案,我也是醉了。。
文章略長,主要講述的是我的探索(踩坑)過程,想要直接看解決方法的請拉到最后,拿走不謝~
過程
先說一下問題所在,比如說,現在有一個表,體溫測量。結構如下:
假設我們每隔一段時間去給用戶測量一次體溫,那么同一個用戶就會產生多條記錄。現在我們想要查詢出每一個用戶最新一條測量數據,怎么查?
接下來我說說我的踩坑歷程:
是不是覺得很簡單,先分組,把重復的數據排掉:
select * from tplay_temperature_record group by user_id;
查詢結果:
我去,不對啊,我想要的是最新的一條,id為51的那條數據才是我想要的啊,怎么給我返回了id為50的?不行,看來我得先排好序,再進行排重,(這個時候我以為group by拿的是第一條):
第一步,先排序:
select * from tplay_temperature_record order by create_time desc;
看到結果,已經排好序了。
然后我們用到子查詢去進行分組:
select * from (select * from tplay_temperature_record order by create_time) as a group by a.user_id;
結果:
我去,不對啊,id為51的那條,咋又給我整沒了。
然后我開始在網上各種搜,在這個地址:https://blog.csdn.net/weixin_38450840/article/details/88836170
發現有人這樣說:
卧槽,這樣子的嗎?原諒我年少無知,才疏學淺,那么我們試試,加上limit:
select * from (select * from tplay_temperature_record order by create_time limit 100) as a group by a.user_id;
結果:
還是一樣,沒有任何改變,我不知道是不是mysql版本太低的原因,我用的是5.5.62,反正就是沒效果。
再看看其他大神的思路吧
於是我找到了這篇文章:https://blog.csdn.net/u012660464/article/details/78605078/
這篇文章的核心思想是:先分組,再排序。
對啊,我們想的是先排序再分組,如果反過來呢?
文章里說到:
按照他說的,寫一個:
SELECT * FROM (select * from tplay_temperature_record order by user_id, create_time DESC) b GROUP BY b.user_id;
結果:
啥情況,還是不對?接着往下翻,看到底下評論一堆叫苦連天的。。
好吧,看來廣大網友和我一樣,沒從這篇文章中獲得什么~
解決
喜聞樂見的環節來了,在無數次的掙扎之后,終於獲得了正確的方法,也是參考了下面這篇文章,感謝大神!
地址:https://www.cnblogs.com/afei-happy/p/3783520.html
核心思想,兩個表的思想,就是先分組作為另一個表,然后進行子查詢,用user_id去關聯,對結果進行排序。
上步驟:
第一步,分組,排除重復,保留想要的哪一行記錄。這里我們是按照user_id排重,查詢時間最近的那條,就可以這樣寫:
SELECT user_id, max(create_time) max_day, temperature FROM tplay_temperature_record GROUP BY user_id
第二步,子查詢,把上述的查詢結果當成另一個表B,然后原表當成表A,用user_id去關聯,然后對查詢到的結果進行排序。
SELECT A.* FROM tplay_temperature_record A, ( SELECT user_id, max(create_time) max_day, temperature FROM tplay_temperature_record GROUP BY user_id ) B WHERE A.user_id = B.user_id AND A.create_time = B.max_day ORDER BY A.create_time DESC
結果:
完美!
總結一下,這一類問題,看似簡單,其實復雜。
我自己感覺這個問題有兩個難點:
1、group by分組后如何保留自己想要的那一行數據?搭配聚合方法,或許有奇效
2、分組后的數據如何排序?其實不太好排序,為何不變通一下,分成兩個表,然后關聯一下查詢再排序呢?
除了這種方法,肯定有其他的,如果有其他方法的,希望在評論區大家一起討論下。
---------------------------------------------------------------------------------------------------------------------------------------
不好意思,找到一個更簡單的寫法:
SELECT *, max(create_time) max_day FROM tplay_temperature_record GROUP BY user_id ORDER BY max_day DESC
都不需要用到“兩個表”的思想。