Mysql递归查询之GROUP_CONCAT限制返回长度跳坑指南

背景

最近sql写的有点多,有一张组织机构表,那么我需要递归查询出父机构下面的所有子机构,这是需求的第一步,第二步我需要根据这些机构的id去关联数据做统计。对于mysql的递归,应该是没有可以直接使用的函数去完成的。那么我选择借助一下变量来完成这个递归查询。

表结构

表结构我进行简化,无关字段就不展示了。
表结构很清晰:
1.parent_id作为上级id冗余存储在当前行中
2.当前行标记除了depth层级
目前看只有条件1对我们本次查询有用。

CREATE TABLE `iam_org` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '上级ID',
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL COMMENT '名称',
  `depth` smallint(6) NOT NULL DEFAULT '1' COMMENT '层级',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2099005353 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Mysql递归查询

1.2065658200是根节点id
2.子查询是将每层的id、childrenId以及层级查出来
3.外层查询通过FIND_IN_SET函数,过滤组织机构表中id存在于子查询中几层的数据。

SELECT ID.LEVEL,
       DATA.*
FROM (
       SELECT @ids                                 AS _ids,
              (SELECT @ids := GROUP_CONCAT(id)
               FROM iam_org
               WHERE FIND_IN_SET(parent_id, @ids)) AS cids,
              @l := @l + 1                         AS LEVEL
       FROM iam_org,
            (SELECT @ids := 2065658200, @l := 0) b
       WHERE @ids IS NOT NULL
     ) ID,
     iam_org DATA
WHERE FIND_IN_SET(DATA.id, ID._ids)
ORDER BY parent_id

bug出现

在验证结果的时候我发现有一个层级我通过count函数查出来的数据,和递归sql查出来的数据不一致,count函数查询出来的结果要大于递归sql查出来的。
count函数查询结果为257条
递归查询出的那一层级的数据大概只有90多条。仔细一看,返回结果中竟然出现了一半的数据。情况十分诡异
看了一下这个数据是由GROUP_CONCAT函数处理并且返回的。
在这里插入图片描述

解决

   果断去查一下官方文档之GROUP_CONCAT发现有这么一段解释:

The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has a default value of 1024. The value can be set higher, although the effective maximum length of the return value is constrained by the value of max_allowed_packet. The syntax to change the value of group_concat_max_len at runtime is as follows, where val is an unsigned integer
SET [GLOBAL | SESSION] group_concat_max_len = val;

   简单来说:

  • GROUP_CONCAT函数返回值有一个最大长度是1024,并且这个值可以改变
  • 当你想在当前会话中临时修改函数返回长度时可以使用如下语句:
	SET SESSION group_concat_max_len = val;
  • 当你想在全局中永久修改函数返回长度时可以使用如下语句:
	SET GLOBAL group_concat_max_len = val;

问题原因很显然就是,GROUP_CONCAT函数返回值已经超过了默认值1024,因此我将它扩大了十倍,再次查询结果正常。
点赞收藏,富婆包养!!!

你可能感兴趣的:(Database,mysql,数据库,sql)