mysql中GROUP BY結合GROUP_CONCAT的使用

出處:http://javeye.iteye.com/blog/558093


我們知道,group by可以將sql查詢結果按照group by後面列進行分類顯示。比如:

Sql代碼  收藏代碼
  1. select columnA,columnB from table group by columnA,columnB  

 則查詢結果將按照columnA和columnB分類顯示。沒有顯示在group by中的列不能直接作爲返回列放在sql語句中,比如如下sql就是不正確的

Sql代碼  收藏代碼
  1. select columnA,columnC from table group by columnA   

 由於columnC不在group by的範圍之類,所以這樣寫是不對的,所幸的是,group by支持一些sql 函數的使用,比如SUM,AVG,COUNT等等。這些都比較常用,今天我要記錄下的是這個不常用的GROUP_CONCAT。

 

有一個需求,需要用到group by 才能實現,可是,我同是還需要返回某列的所有結果,(注意,不是做avg,sum等操作,我要枚舉這列的所有結果),那麼就可以用到GROUP_CONCAT。

舉個例子:

我有一張數據庫表結構如下:

列名 含義
year 年份
month 月份
volumn 期數

該表存儲了某雜誌的年份,月份和期數。如果需求對該表內容作如下顯示:

 

2010年12月 第1期  第2期  第3期 第4期
2010年11月 第1期  第2期  第3期 第4期  第5期
2010年10月 第1期  第2期  第3期 第4期
2010年9月 第1期  第2期  第3期 第4期  第5期
2010年8月 第1期  第2期  第3期 第4期 

 

sql該怎麼寫呢?按照年份和月份做group by?然後按照年份和月份做倒敘排列?

Sql代碼  收藏代碼
  1. select year,month from magazine group by year,month order by year desc,month desc  

 那具體的期數信息就丟了?能不能做group by的時候,還能返回在某個年份year和月份month分組下的所有期數volumn信息?(某個年份+月份下的期數信息是不固定的,只能通過數據庫查詢才能獲得)

該是GROUP_CONCAT上陣的時候了。

Sql代碼  收藏代碼
  1. select year,month GROUP_CONCAT(volumn) from magazine group by year,month order by year descmonth desc  

 這樣,查詢的返回結果類似於:

year month GROUP_CONCAT(volumn)
2010 12 1,2,3,4
2010 11 1,2,3,4,5

 

不錯吧?

還有點問題需要補充下,就是作爲GROUP_CONCAT函數參數的字段,如過返回值爲string,則上面的sql語句已經沒有問題,但是如果是number,則返回的GROUP_CONCAT(volumn)值爲BLOB類型(其實上面例子返回的就是一個blob類型,我只是爲了演示的方便),需要做一下轉化。

Sql代碼  收藏代碼
  1. select year,month GROUP_CONCAT(conv( oct( volumn ) , 8, 10 )) from magazine group by year,month order by year descmonth desc  

 上面的sql對volumn做了一個從8進制到10進制的轉換,這樣返回的就是一個字符串了。

mysql默認會以‘,’來分隔多的值,如果想用其他的分隔符來分隔返回結果,比如期望返回值是這樣的:1|2|3|4

這可以用SEPARATOR來搞定。

Sql代碼  收藏代碼
  1. select year,month GROUP_CONCAT(conv( oct( volumn ) , 8, 10 ) SEPARATOR '|'from magazine group by year,month order by year descmonth desc   

更牛的是,你甚至可以對返回的volumn進行排序!!

Sql代碼  收藏代碼
  1. select year,month GROUP_CONCAT(conv( oct( volumn ) , 8, 10 ) order by volumn desc SEPARATOR '|'from magazine group by year,month order by year descmonth desc  

 

這個不常用的東東,還是比較好用的。

 

分享到:  
評論
2 樓 javeye 2010-07-05   引用
記錄下:下面這樣會交換兩條記錄的id。
Java代碼  收藏代碼
  1. update test t1,test t2 set t1.id=t2.id,t2.id=t1.id where t1.id=1 and t2.id=2  
1 樓 javeye 2009-12-29   引用
在mysql中,GROUP_CONCAT函數的語法如下:
Java代碼  收藏代碼
  1. GROUP_CONCAT([DISTINCT] expr [,expr ...]  
  2.              [ORDER BY {unsigned_integer | col_name | expr}  
  3.                  [ASC | DESC] [,col_name ...]]  
  4.              [SEPARATOR str_val])  

以下內容轉載於:http://www.cnblogs.com/Arlen/archive/2008/04/30/1177648.html
GROUP_CONCAT使用陷阱

1.int字段的連接陷阱

當你用group_concat的時候請注意,連接起來的字段如果是int型,一定要轉換成char再拼起來,
否則在你執行後(ExecuteScalar或者其它任何執行SQL返回結果的方法)返回的將不是一個逗號隔開的串,
而是byte[]。

該問題當你在SQLyog等一些工具中是體現不出來的,所以很難發現。

Sql代碼  收藏代碼
  1. select group_concat(ipaddress) from t_ip 返回逗號隔開的串  
  2. select group_concat(id) from t_ip 返回byte[]  
  3. select group_concat(CAST(id as char)) from t_dep 返回逗號隔開的串  
  4. select group_concat(Convert(id , char)) from t_dep 返回逗號隔開的串  


附Cast,convert的用法:
CAST(expr AS type), CONVERT(expr,type) , CONVERT(expr USING transcoding_name)
CAST() 和CONVERT() 函數可用來獲取一個類型的值,併產生另一個類型的值。

這個類型 可以是以下值其中的一個: 

Sql代碼  收藏代碼
  1. BINARY[(N)]  
  2. CHAR[(N)]  
  3. DATE  
  4. DATETIME  
  5. DECIMAL  
  6. SIGNED [INTEGER]  
  7. TIME  
  8. UNSIGNED [INTEGER]  


2.長度陷阱
用group_concat連接字段的時候是有長度限制的,並不是有多少連多少。但你可以設置一下。

使用group_concat_max_len系統變量,你可以設置允許的最大長度。 
程序中進行這項操作的語法如下,其中 val 是一個無符號整數:
Sql代碼  收藏代碼
  1. SET [SESSION | GLOBAL] group_concat_max_len = val;  

若已經設置了最大長度, 則結果被截至這個最大長度。

在SQLyog中執行 SET GLOBAL group_concat_max_len = 10 後,重新打開SQLyog,設置就會生效。

請注意,這種方式只是臨時的,如要長久的修改,則需要修改mysql的配置節。

到my.cnf的mysqld節點下加上group_concat_max_len =99999……

重啓mysql。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章