背景
最近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,因此我将它扩大了十倍,再次查询结果正常。 点赞收藏,富婆包养!!!
|