国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

mysql中過濾重復記錄之distinct用法

2024-07-24 12:38:42
字體:
來源:轉載
供稿:網友

本文章主要是講述了關于利用mysql中distinct來過濾一些重啟的記錄,有需要的朋友可參考一下.

下面我們就通過幾個簡單的 Query 示例來展示一下 DISTINCT 的實現.

1.首先看看通過松散索引掃描完成 DISTINCT 的操作,代碼如下:

  1. sky@localhost : example 11:03:41> EXPLAIN SELECT DISTINCT group_id  
  2.     -> FROM group_messageG 
  3. *************************** 1. row *************************** 
  4.            id: 1  --Vevb.com 
  5.   SELECT_type: SIMPLE 
  6.         table: group_message 
  7.          type: range 
  8. possible_keys: NULL 
  9.           key: idx_gid_uid_gc 
  10.       key_len: 4 
  11.           ref: NULL 
  12.          rows: 10 
  13.         Extra: Using index for group-by 
  14. 1 row in set (0.00 sec) 

我們可以很清晰的看到,執行計劃中的 Extra 信息為“Using index for group-by”,這代表什么意思?為什么我沒有進行 GROUP BY 操作的時候,執行計劃中會告訴我這里通過索引進行了 GROUP BY 呢?其實這就是于 DISTINCT 的實現原理相關的,在實現 DISTINCT的過程中,同樣也是需要分組的,然后再從每組數據中取出一條返回給客戶端。而這里的 Extra 信息就告訴我們,MySQL 利用松散索引掃描就完成了整個操作。當然,如果 MySQL Query Optimizer 要是能夠做的再人性化一點將這里的信息換成“Using index for distinct”那就更好更容易讓人理解了,呵呵。

2.我們再來看看通過緊湊索引掃描的示例,代碼如下:

  1. sky@localhost : example 11:03:53>  EXPLAIN SELECT DISTINCT user_id  
  2.     -> FROM group_message 
  3.     -> WHERE group_id = 2G 
  4. *************************** 1. row *************************** 
  5.            id: 1 
  6.   SELECT_type: SIMPLE 
  7.         table: group_message 
  8.          type: ref 
  9. possible_keys: idx_gid_uid_gc 
  10.           key: idx_gid_uid_gc 
  11.       key_len: 4 
  12.           ref: const 
  13.          rows: 4 
  14.         Extra: Using WHERE; Using index 
  15. 1 row in set (0.00 sec) 

這里的顯示和通過緊湊索引掃描實現 GROUP BY 也完全一樣,實際上,這個 Query 的實現過程中,MySQL 會讓存儲引擎掃描 group_id = 2 的所有索引鍵,得出所有的 user_id,然后利用索引的已排序特性,每更換一個 user_id 的索引鍵值的時候保留一條信息,即可在掃描完所有 gruop_id = 2 的索引鍵的時候完成整個 DISTINCT 操作.

3.下面我們在看看無法單獨使用索引即可完成 DISTINCT 的時候會是怎樣,代碼如下:

  1. sky@localhost : example 11:04:40> EXPLAIN SELECT DISTINCT user_id  
  2.     -> FROM group_message 
  3.     -> WHERE group_id > 1 AND group_id < 10G 
  4. *************************** 1. row *************************** 
  5.            id: 1 
  6.   SELECT_type: SIMPLE 
  7.         table: group_message 
  8.          type: range 
  9. possible_keys: idx_gid_uid_gc 
  10.           key: idx_gid_uid_gc 
  11.       key_len: 4 
  12.           ref: NULL 
  13.          rows: 32 
  14.         Extra: Using WHERE; Using index; Using temporary 
  15. 1 row in set (0.00 sec) 

當 MySQL 無法僅僅依賴索引即可完成 DISTINCT 操作的時候,就不得不使用臨時表來進行相應的操作了。但是我們可以看到,在 MySQL 利用臨時表來完成 DISTINCT 的時候,和處理 GROUP BY 有一點區別,就是少了 filesort。實際上,在 MySQL 的分組算法中,并不一定非要排序才能完成分組操作的,這一點在上面的 GROUP BY 優化小技巧中我已經提到過了。實際上這里 MySQL 正是在沒有排序的情況下實現分組最后完成 DISTINCT 操作的,所以少了 filesort 這個排序操作。

4.最后再和 GROUP BY 結合試試看,代碼如下:

  1. sky@localhost : example 11:05:06> EXPLAIN SELECT DISTINCT max(user_id)  
  2.     -> FROM group_message 
  3.     -> WHERE group_id > 1 AND group_id < 10 
  4.     -> GROUP BY group_idG 
  5. *************************** 1. row *************************** 
  6.            id: 1 
  7.   SELECT_type: SIMPLE 
  8.         table: group_message 
  9.          type: range 
  10. possible_keys: idx_gid_uid_gc 
  11.           key: idx_gid_uid_gc 
  12.       key_len: 4 
  13.           ref: NULL 
  14.          rows: 32 
  15.         Extra: Using WHERE; Using index; Using temporary; Using filesort 
  16. 1 row in set (0.00 sec) 

最后我們再看一下這個和 GROUP BY 一起使用帶有聚合函數的示例,和上面第三個示例相比,可以看到已經多了 filesort 排序操作了,正是因為我們使用了 MAX 函數的緣故。要取得分組后的 MAX 值,又無法使用索引完成操作,只能通過排序才行了。

在使用mysql時,有時需要查詢出某個字段不重復的記錄,雖然mysql提供有distinct這個關鍵字來過濾掉多余的重復記錄只保留一條,但往往只用它來返回不重復記錄的條數,而不是用它來返回不重記錄的所有值。其原因是distinct只能返回它的目標字段,而無法返回其它字段,這個問題讓我困擾了很久

下面先來看看例子,代碼如下:

  1. table  
  2. id name  
  3. 1 a  
  4. 2 b  
  5. 3 c  
  6. 4 c  
  7. 5 b 

庫結構大概這樣,這只是一個簡單的例子,實際情況會復雜得多,比如我想用一條語句查詢得到name不重復的所有數據,那就必須使用distinct去掉多余的重復記錄,代碼如下:

select distinct name from table

得到的結果是:

  1. name  
  2. a  
  3. b  

好像達到效果了,可是,我想要得到的是id值呢?改一下查詢語句吧,代碼如下:

select distinct name, id from table

結果會是如下代碼:

  1. id name  
  2. 1 a  
  3. 2 b  
  4. 3 c  
  5. 4 c  
  6. 5 b 

distinct怎么沒起作用?作用是起了的,不過他同時作用了兩個字段,也就是必須得id與name都相同的才會被排除,我們再改改查詢語句,代碼如下:

select id, distinct name from table

很遺憾,除了錯誤信息你什么也得不到,distinct必須放在開頭,難到不能把distinct放到where條件里?能,照樣報錯.

試了半天,也不行,最后在mysql手冊里找到一個用法,用group_concat(distinct name)配合group by name實現了我所需要的功能,興奮,天佑我也,趕快試試

報錯,郁悶,連mysql手冊也跟我過不去,先給了我希望,然后又把我推向失望,好狠那.

再仔細一查,group_concat函數是4.1支持,暈,我4.0的。沒辦法,升級,升完級一試,成功。。。。。。

終于搞定了,不過這樣一來,又必須要求客戶也升級了,突然靈機一閃,既然可以使用group_concat函數,那其它函數能行嗎?趕緊用count函數一試,成功,我。。。。。。。想哭啊,費了這么多工夫。。。。。。。。原來就這么簡單。。。。。。

現在將完整語句放出,代碼如下:

select id,name, count(distinct name) from table group by name

結果,代碼如下:

  1. id name count(distinct name)  
  2. 1 a 1  
  3. 2 b 1  
  4. 3 c 1 

最后一項是多余的,不用管就行了,目的達到,哦,對,再順便說一句,group by 必須放在 order by 和 limit之前,不然會報錯,差不多了,我繼續忙碌。。。。。。

原文:這篇文章是我從別人那里轉來的,在自己的項目中也遇到了這樣的問題,我的sql語句是向下面這樣寫的:

  1. SELECT attention_join.memberID,nickName,headpic,attention_join.time 
  2.  FROM attention_join 
  3.      JOIN member ON attention_join.memberID = member.memberID 
  4.      JOIN member_meta ON member.memberID = member_meta.memberID 
  5.  GROUP BY attention_join.memberID 
  6.  ORDER BY attention_join.time DESC 

意思是 '按 加入/關注 小組的時間降序,查出小組內的會員' ,但是語句里并沒有用到向上文說的count()關鍵字,這個也讓我很不解,mysql沒有詳細的學習過,它的 group by 關鍵字的用法好像和 sqlserver 的有很大不同,這個等有時間了,在查查看吧,現在沒有時間了

哦,對了,我的mysql版本是:服務器版本: 5.1.54-1 ubuntu4,協議版本: 10

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 余干县| 博爱县| 周口市| 上杭县| 阳西县| 许昌县| 达日县| 南召县| 河西区| 泗水县| 县级市| 乐亭县| 突泉县| 沛县| 石台县| 弋阳县| 平谷区| 东兴市| 邵阳市| 伊宁县| 水城县| 赫章县| 保康县| 河东区| 新邵县| 资中县| 庄河市| 郑州市| 潮安县| 镇康县| 灵台县| 延川县| 达日县| 田阳县| 峡江县| 阿图什市| 金坛市| 鹤壁市| 芒康县| 扬州市| 辰溪县|