眾所周知,一般在mysql過濾相同記錄時常用的關鍵字是distinct, group by等關鍵字,但是怎麼過濾兩個不同的字段相同的記錄呢。
以下是問題需求:
有一張表chat_history中存在字段id,from_uid,to_uid等字段,其中id為自增id,from_uid為消息的發送方的uid,to_uid為接收方的uid,現在需要獲得某一個uid的最新聯系人。
首先的第一個想法就是對from_uid,to_uid進行group by操作然後獲得max(id)過濾出from_uid或者to_uid等於目標uid的值。
按照這種想法我們可以獲得如下的sql語句
select max(id) as mid,from_uid,to_uid from chat_history where from_uid="xxxxxx" or to_uid = "xxxxxx" group by from_uid, to_uid order by mid.
這時我們查看結果可以很明顯的發現一個問題,假設兩個相互通信的uid1和uid2,我們通過上面的sql語句獲取到兩條數據from_uid=uid1,to_uid=uid2和from_uid=uid2,to_uid=uid1。當然這也不是問題,數據我們已經查到了,我們可以通過程序再對結果進行一次合並,我們就可以獲得我們希望獲得的數據。
在最近聯系比較少的情況下,上述的處理方法並沒有什麼不合適的地方,但是當最近聯系人較多時,我們可能會想到使用分頁對列表頁進行分頁。但是上述的做法很明顯就已經達不到我們的預期了,我們希望將其整合到一條sql語句中,並且可以使用limit關鍵字。
通過觀察,我們希望過濾諸如from_uid=uid1,to_uid=uid2和from_uid=uid2,to_uid=uid1這樣的記錄,第一反應就是我們可以在上述的sql語句作為臨時表,再在外層加sql語句進行處理,當然這種方法從邏輯上是成立的,但是他是以犧牲效率來實現的,博主個人是比較反感使用中間表的。
通過對上述結果的觀察,我們可以獲得這樣一種信息,uid1,uid2是不是可以作為一個字段進行處理呢,在mysql中存在關鍵子concat這是對兩個字段進行合並操作,但是簡單的concat(from_uid,to_uid)還是達不到我們希望的結果,但是mysql提供了邏輯運算,case 操作。
可以將以上sql語句更改如下:
SELECT max( id ) AS mid, from_uid, to_uid, CASE to_uid WHEN 'xxx' THEN concat( to_uid, from_uid ) ELSE concat( from_uid, to_uid ) END AS to_from_uid FROM chat_history WHERE to_uid = 'xxx' OR from_uid = 'xxx' GROUP BY to_from_uid ORDER BY mid DESC LIMIT 0,20