啰嗦下,之所以在这里提到这个函数,是有在项目中按照某个字段分组后,想要获取该组下其它相关的字段的值的需求,当时在想,我在数据库中按照某个字段分组后,其它非分组字段的值就不准确了,然鹅我想获取改组下某个具体字段的值,想了下,大脑中全是些很麻烦的实现方案,后来跟大佬把问题背景一题,大佬想了几分钟给了我一个函数,那就是group_concat。
1.group_concat
获取组内非NULL字符串,如果没有NULL值则返回NULL。
完整语法如下:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val])
2.实例:
假设我们拿dye_production_shcedules 这个表数据为例
先看下部分表结构:
show create table dye_production_schedules;
dye_production_schedules | CREATE TABLE `dye_production_schedules` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`dye_code` varchar(255) COLLATE ***************
`order_id` int(10) unsigned DEFAULT NULL COMMENT '其它主表id',
`order_detail_id` int(10) unsigned DEFAULT NULL COMMENT '其它主表明细ID',
`product_id` int(10) unsigned DEFAULT NULL COMMENT '关联产品id',
`customer_color_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '客户颜色名称',
关键看下order_id 和 order_detail_id 这连个字段,order_id 为主表id,order_detail_id为主表明细id,一对多关系,在这个表中也是如此,一对多关系!!
我们现在按照order_id来进行分组
mysql> select order_id,dye_code,product_id,customer_color_name from dye_production_schedules where
-> deleted_at is null and batch_num <> '' group by order_id limit 10;
+----------+----------------+------------+----------------------------------------------------------+
| order_id | dye_code | product_id | customer_color_name |
+----------+----------------+------------+----------------------------------------------------------+
| 177 | POD170803005-6 | 520 | 黑色black |
| 208 | POD170804004-1 | 479 | Black 黑色 |
| 255 | POD170731001-3 | 488 | Neon Peach 橘红色 |
| 256 | POD170731001-4 | 490 | Grey Geo JTJL6-印花 |
| 292 | POD170822015-1 | 54 | 漂白BRIGHT WHITE(PTN#11-0601) JS97680 |
| 293 | POD170822011-1 | 54 | STRONG BLUE (PTN#18-4051) 工厂色号:JS96672(此为衫身) |
| 296 | POD170822016-1 | 54 | ENGLISH ROSE(PTN#13-1310) 工厂色号:JS97112(此为衫身) |
| 310 | POD170826009-1 | 487 | Coral 橘红色 工厂色号:YB41536 OK"B' 单染涤 |
| 348 | POD170826008-1 | 614 | 59X NAVY 海蓝 工厂色号:JS97596 OK"M" |
| 369 | POD170921015-1 | 331 | Forged Iron 棕灰色/JS97530 |
+----------+----------------+------------+----------------------------------------------------------+
10 rows in set (0.05 sec)
因为是按照order_id进行的分组,所以除了这个字段值外,其它字段值是不准确的,那么,我现在也需要获取order_detail_id,该怎么处理呢?
select order_id,dye_code,product_id,customer_color_name,group_concat(order_detail_id) from dye_production_schedules where
deleted_at is null and batch_num <> '' group by order_id limit 10;
可以看到的是按照order_id分组后,再取出其对应的order_detail_id时,这一列很多数据,而且很多重复的,有时候我们不需要重复的数据,可以在具体的字段名前加distinct 来进行去重处理。
mysql> select order_id,dye_code,product_id,customer_color_name,group_concat(distinct order_detail_id ) from dye_production_schedules where
-> deleted_at is null and batch_num <> '' group by order_id limit 10;
+----------+----------------+------------+----------------------------------------------------------+---------------------------------------------------+
| order_id | dye_code | product_id | customer_color_name | group_concat(distinct order_detail_id ) |
+----------+----------------+------------+----------------------------------------------------------+---------------------------------------------------+
| 177 | POD170803005-6 | 520 | 黑色black | 964,961,962,966,972,969,970,971,967 |
| 208 | POD170804004-1 | 479 | Black 黑色 | 1064 |
| 255 | POD170731001-3 | 488 | Neon Peach 橘红色 | 1255,1256 |
| 256 | POD170731001-4 | 490 | Grey Geo JTJL6-印花 | 1259,1260,1261,1262,1263,1264,1265,1266,1267,1268 |
| 292 | POD170822015-1 | 54 | 漂白BRIGHT WHITE(PTN#11-0601) JS97680 | 1791,1792,1793,1794 |
| 293 | POD170822011-1 | 54 | STRONG BLUE (PTN#18-4051) 工厂色号:JS96672(此为衫身) | 1775,1776,1777,1778 |
| 296 | POD170822016-1 | 54 | ENGLISH ROSE(PTN#13-1310) 工厂色号:JS97112(此为衫身) | 1795,1796,1797,1798 |
| 310 | POD170826009-1 | 487 | Coral 橘红色 工厂色号:YB41536 OK"B' 单染涤 | 1460 |
| 348 | POD170826008-1 | 614 | 59X NAVY 海蓝 工厂色号:JS97596 OK"M" | 2166,2167,2168 |
| 369 | POD170921015-1 | 331 | Forged Iron 棕灰色/JS97530 | 1670 |
+----------+----------------+------------+----------------------------------------------------------+---------------------------------------------------+
10 rows in set (0.03 sec)
从结果列中可以看到,group_concat 的字段排列很有规律,我现在想让它倒序排列,可以试试order by order_detail_id desc。
mysql> select order_id,dye_code,product_id,customer_color_name,group_concat(distinct order_detail_id order by order_detail_id desc) from dye_production_schedules where
-> deleted_at is null and batch_num <> '' group by order_id limit 10;
+----------+----------------+------------+----------------------------------------------------------+----------------------------------------------------------------------+
| order_id | dye_code | product_id | customer_color_name | group_concat(distinct order_detail_id order by order_detail_id desc) |
+----------+----------------+------------+----------------------------------------------------------+----------------------------------------------------------------------+
| 177 | POD170803005-6 | 520 | 黑色black | 972,971,970,969,967,966,964,962,961 |
| 208 | POD170804004-1 | 479 | Black 黑色 | 1064 |
| 255 | POD170731001-3 | 488 | Neon Peach 橘红色 | 1256,1255 |
| 256 | POD170731001-4 | 490 | Grey Geo JTJL6-印花 | 1268,1267,1266,1265,1264,1263,1262,1261,1260,1259 |
| 292 | POD170822015-1 | 54 | 漂白BRIGHT WHITE(PTN#11-0601) JS97680 | 1794,1793,1792,1791 |
| 293 | POD170822011-1 | 54 | STRONG BLUE (PTN#18-4051) 工厂色号:JS96672(此为衫身) | 1778,1777,1776,1775 |
| 296 | POD170822016-1 | 54 | ENGLISH ROSE(PTN#13-1310) 工厂色号:JS97112(此为衫身) | 1798,1797,1796,1795 |
| 310 | POD170826009-1 | 487 | Coral 橘红色 工厂色号:YB41536 OK"B' 单染涤 | 1460 |
| 348 | POD170826008-1 | 614 | 59X NAVY 海蓝 工厂色号:JS97596 OK"M" | 2168,2167,2166 |
| 369 | POD170921015-1 | 331 | Forged Iron 棕灰色/JS97530 | 1670 |
+----------+----------------+------------+----------------------------------------------------------+----------------------------------------------------------------------+
group_concat 函数,默认是以","(逗号)分隔开的,当然你也可以自定义分隔符,具体做法是在表达式后面使用SEPARATOR 指定分隔符。
例如:
select order_id,dye_code,product_id,customer_color_name,
group_concat(distinct order_detail_id order by order_detail_id desc SEPARATOR '|')
from dye_production_schedules where
deleted_at is null and batch_num <> '' group by order_id limit 10;
mysql> select order_id,dye_code,product_id,customer_color_name,
-> group_concat(distinct order_detail_id order by order_detail_id desc SEPARATOR '|')
-> from dye_production_schedules where
-> deleted_at is null and batch_num <> '' group by order_id limit 10;
+----------+----------------+------------+----------------------------------------------------------+-------------------------------------------------------------------------------------+
| order_id | dye_code | product_id | customer_color_name | group_concat(distinct order_detail_id order by order_detail_id desc SEPARATOR '|') |
+----------+----------------+------------+----------------------------------------------------------+-------------------------------------------------------------------------------------+
| 177 | POD170803005-6 | 520 | 黑色black | 972|971|970|969|967|966|964|962|961 |
| 208 | POD170804004-1 | 479 | Black 黑色 | 1064 |
| 255 | POD170731001-3 | 488 | Neon Peach 橘红色 | 1256|1255 |
| 256 | POD170731001-4 | 490 | Grey Geo JTJL6-印花 | 1268|1267|1266|1265|1264|1263|1262|1261|1260|1259 |
| 292 | POD170822015-1 | 54 | 漂白BRIGHT WHITE(PTN#11-0601) JS97680 | 1794|1793|1792|1791 |
| 293 | POD170822011-1 | 54 | STRONG BLUE (PTN#18-4051) 工厂色号:JS96672(此为衫身) | 1778|1777|1776|1775 |
| 296 | POD170822016-1 | 54 | ENGLISH ROSE(PTN#13-1310) 工厂色号:JS97112(此为衫身) | 1798|1797|1796|1795 |
| 310 | POD170826009-1 | 487 | Coral 橘红色 工厂色号:YB41536 OK"B' 单染涤 | 1460 |
| 348 | POD170826008-1 | 614 | 59X NAVY 海蓝 工厂色号:JS97596 OK"M" | 2168|2167|2166 |
| 369 | POD170921015-1 | 331 | Forged Iron 棕灰色/JS97530 | 1670 |
+----------+----------------+------------+----------------------------------------------------------+-------------------------------------------------------------------------------------+
3.一些杂谈
group_concat 这个函数的最大长度输出结果值取决于系统变量:group_concat_max_len,其值默认为1024,超过其最大长度会被截断哦。
小试一下下:
mysql> select @@group_concat_max_len;
+------------------------+
| @@group_concat_max_len |
+------------------------+
| 1024 |
+------------------------+
1 row in set (0.00 sec)
mysql> set group_concat_max_len = 10;
Query OK, 0 rows affected (0.00 sec)
mysql> select order_id,dye_code,product_id,customer_color_name,
-> group_concat(distinct order_detail_id order by order_detail_id desc SEPARATOR '|')
-> from dye_production_schedules where
-> deleted_at is null and batch_num <> '' group by order_id limit 10;
+----------+----------------+------------+----------------------------------------------------------+-------------------------------------------------------------------------------------+
| order_id | dye_code | product_id | customer_color_name | group_concat(distinct order_detail_id order by order_detail_id desc SEPARATOR '|') |
+----------+----------------+------------+----------------------------------------------------------+-------------------------------------------------------------------------------------+
| 177 | POD170803005-6 | 520 | 黑色black | 972|971|97 |
| 208 | POD170804004-1 | 479 | Black 黑色 | 1064 |
| 255 | POD170731001-3 | 488 | Neon Peach 橘红色 | 1256|1255 |
| 256 | POD170731001-4 | 490 | Grey Geo JTJL6-印花 | 1268|1267| |
| 292 | POD170822015-1 | 54 | 漂白BRIGHT WHITE(PTN#11-0601) JS97680 | 1794|1793| |
| 293 | POD170822011-1 | 54 | STRONG BLUE (PTN#18-4051) 工厂色号:JS96672(此为衫身) | 1778|1777| |
| 296 | POD170822016-1 | 54 | ENGLISH ROSE(PTN#13-1310) 工厂色号:JS97112(此为衫身) | 1798|1797| |
| 310 | POD170826009-1 | 487 | Coral 橘红色 工厂色号:YB41536 OK"B' 单染涤 | 1460 |
| 348 | POD170826008-1 | 614 | 59X NAVY 海蓝 工厂色号:JS97596 OK"M" | 2168|2167| |
| 369 | POD170921015-1 | 331 | Forged Iron 棕灰色/JS97530 | 1670 |
+----------+----------------+------------+-------------------------------------------------
PS:如果你在执行group by操作的时候,你的mysql连接客户端报了什么group by full 严格等的错误,那估计是你mysql版本是5.7.2的,那是因为mysql 5.7.2启用了严格模式,很好解决
使用 select @@sql_mode;把sql_mode 改成非only_full_group_by模式(我这里并没有出现,所以不再赘述,我的mysql版本5.7.9)