DROP TABLE IF EXISTS `merchant_region`;
CREATE TABLE `merchant_region` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NULL DEFAULT NULL,
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `merchant_region` VALUES (1, 0, '1');
INSERT INTO `merchant_region` VALUES (2, 0, '2');
INSERT INTO `merchant_region` VALUES (3, 0, '3');
INSERT INTO `merchant_region` VALUES (4, 1, '1-1');
INSERT INTO `merchant_region` VALUES (5, 4, '1-1-1');
INSERT INTO `merchant_region` VALUES (6, 4, '1-1-2');
INSERT INTO `merchant_region` VALUES (7, 6, '1-1-2-1');
INSERT INTO `merchant_region` VALUES (8, 2, '2-1');
INSERT INTO `merchant_region` VALUES (9, 2, '2-2');
INSERT INTO `merchant_region` VALUES (10, 3, '3-1');
INSERT INTO `merchant_region` VALUES (11, 1, '1-2');
INSERT INTO `merchant_region` VALUES (12, 11, '1-2-1');
示例sql
select * from merchant_region;
-- 发现使用字符型和使用数字类型查询结果在显示上不一致,所以需要转
select @ids;
select @ids:= 0;
select @ids:= '0';
select @ids:= cast(0 as char);
-- 核心(作最坏的打算->假设表中数据所代表的每一个节点都是上一个节点的子节点)
select @ids as _ids,
(
select @ids:=group_concat(mr.id)
from merchant_region mr
where find_in_set(mr.parent_id,@ids)
)
from merchant_region
-- 为了更好的理解上面这个逻辑,可以执行如下的sql帮助理解
select @ids := null;
select @ids := if(@ids is null,1,@ids:=@ids+1) ,mr.* from merchant_region mr
-- 最终写法
select
mr.*
from
merchant_region mr
inner join (select @ids:= cast(0 as char)) t1 -- 将@ids初始化,并且将数字转为字符类型
inner join (
select @ids as _ids1,
(
select @ids:=group_concat(mr.id)
from merchant_region mr
where find_in_set(mr.parent_id,@ids)
) as _ids2
from merchant_region
where @ids is not null -- 排除掉后面都是null的数据行
) t2
where
find_in_set(mr.id,t2._ids1) -- 这里选择_ids1或_ids2来决定是否包含自身
-- 使用示例
<select id="selectHierarchyRegion" resultType="com.anbao.ambientMonitor.data.dto.region.MerchantRegionCustomPropertyDTO">
SELECT
mr.id,
mr.region_name AS label,
mr.parent_id,
mr.region_remark,
mur.merchant_sub_user_id
FROM
merchant_user_region mur
LEFT JOIN merchant_region mr ON mr.id = mur.merchant_region_id
,(SELECT @ids := 0) b
,(SELECT @ids AS _ids,(SELECT @ids := GROUP_CONCAT(id) FROM merchant_region WHERE FIND_IN_SET(parent_id, @ids)) AS cids FROM merchant_region WHERE @ids IS NOT NULL ) a
WHERE
mur.merchant_sub_user_id = #{merchantUserId}
AND FIND_IN_SET(mur.merchant_region_id,a._ids)
AND mr.merchant_id = #{merchantId}
AND mr.region_classify = 1
AND mr.is_del = 0
ORDER BY CONVERT(mr.region_name USING gbk)
</select>
有时候,上面这条sql查询,每次查询的结果有不一致的情况,原因不明。但须执行下面这条代码,就可以解决,不知道为什么
baseMapper.removeCache(1L);
<update id="removeCache">
SELECT
@ids AS _ids,
(
SELECT
@ids := GROUP_CONCAT(id)
FROM
merchant_region
WHERE
FIND_IN_SET(parent_id, @ids)
) AS cids
FROM
merchant_region,
(SELECT @ids := #{regionId}) b
WHERE
@ids IS NOT NULL
</update>
上面查询,有的时候查出的来的结果不一致,可以先把后面的查询先查出来作为临时表,再使用Left JOIN连接起来,下面的CAST是因为单独查询这个临时表,也有点问题。
SELECT
d.id,
d.name,
d.parent_id
FROM
dept d
LEFT JOIN(
SELECT * FROM (
(SELECT @ids := CAST(#{parentId} AS char)) a
, (SELECT @ids AS _ids ,
(SELECT @ids := GROUP_CONCAT(id) FROM dept WHERE FIND_IN_SET(parent_id, @ids)) AS cids
FROM
dept
WHERE
@ids IS NOT NULL
) b
)
) T ON FIND_IN_SET(d.id, T._ids)
WHERE
d.hospital_area_id = #{hospitalAreaId}
AND d.is_del = 0
ORDER BY
d.sort_index DESC
mysql根据父节点递归查询所有子节点
根据一个父节点查询所有子节点(包含自身)
SELECT au.id
FROM (SELECT * FROM t_app_user WHERE parent_id IS NOT NULL) au,
(SELECT @pid := '1') pd
WHERE FIND_IN_SET(parent_id, @pid) > 0
AND @pid := concat(@pid, ',', id)
union select id from t_app_user where id = '1';
根据多个父节点查询所有子节点(包含自身)
SELECT au.id
FROM (SELECT * FROM t_app_user WHERE parent_id IS NOT NULL) au,
(SELECT @pid := '1,4') pd
WHERE FIND_IN_SET(parent_id, @pid) > 0
AND @pid := concat(@pid, ',', id)
union select id from t_app_user where FIND_IN_SET(id,@pid) > 0;
MYSQL根据id递归向下查询所有子级
SELECT
ID.LEVEL,
DATA.*
FROM
(
SELECT
@ids AS _ids,
( SELECT @ids := GROUP_CONCAT( id ) FROM 表名 WHERE FIND_IN_SET( 父级 id字段, @ids ) ) AS cids,
@l := @l + 1 AS LEVEL
FROM
表名,
( SELECT @ids := '条件id', @l := 0 ) b
WHERE
@ids IS NOT NULL
) ID,
表名 DATA
WHERE
FIND_IN_SET( DATA.id, ID._ids )
ORDER BY
LEVEL,
id
示例:
<select id="selectAllSubDeptByDeptIds" resultType="long">
SELECT
d.id
FROM
dept d
INNER JOIN(
SELECT * FROM (
(SELECT @ids :=
'${@org.springframework.util.StringUtils@collectionToCommaDelimitedString(deptIdList)}'
) a
, (SELECT @ids AS _ids ,
(SELECT @ids := GROUP_CONCAT(id) FROM dept WHERE FIND_IN_SET(parent_id, @ids)) AS cids
FROM
dept d
WHERE
@ids IS NOT NULL AND d.is_del = 0
) b
)
) T ON FIND_IN_SET(d.id, T.cids)
WHERE
d.is_del = 0
</select>
示例
<delete id="deleteCourseInvitationSubDepts">
DELETE
FROM
course_invitation ci
WHERE
ci.course_id = #{courseId}
AND FIND_IN_SET (ci.dept_id,
(
SELECT
group_concat( cids )
FROM (
( SELECT @ids :=
'${@org.springframework.util.StringUtils@collectionToCommaDelimitedString(deptIdList)}'
) a,
(SELECT
@ids AS _ids,
(SELECT
@ids := GROUP_CONCAT( id )
FROM
dept
WHERE
FIND_IN_SET( parent_id, @ids )
) AS cids
FROM
dept
WHERE
@ids IS NOT NULL
) b
)
)
)
</delete>
依据上面的原理,我们也可以给查出来的数据添加一个简单的序号,类似于下面这种
select
mr.*,
t1.*,
(@ids:=@ids+1) _ids -- 序号列
from
merchant_region mr
inner join (select @ids:= 0) t1
原理篇
来源:mysql按照天统计报表,当天没有数据,填0
SELECT
@cdate := DATE_ADD(@cdate, INTERVAL - 1 DAY) DAY
FROM
(SELECT
@cdate := DATE_ADD('20171219', INTERVAL + 1 DAY)
FROM
order) t0
LIMIT 7
原文:mysql实现无限层次父子关系查询,并返回当前查询level层级
create table CS_INTCTL_ASSESS_ITEM_GATHER
(
id int(11) PRIMARY key auto_increment,
assess_id VARCHAR(36),
assess_parent_id VARCHAR(36),
name VARCHAR(256)
)
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ( 'c46a67ffa5dc4cd990e9402dd5f21e56', '7540f5592a794ec0982bbea817d4b8ce', '一、组织结构评价(20分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('7d77b36468e04e96a56af4f105225fac', '7540f5592a794ec0982bbea817d4b8ce', '二、经营理念与风格评价(14分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('7540f5592a794ec0982bbea817d4b8ce', 'd24e44cbc0c34452b1da93739adfe716', '内部环境');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('15f1abe4b9544f7d900f6ccec9842256', '13af09d9e8ad4da297e72e3020e290c8', '一、信贷基础管理评价(10分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('73a60d0ed27c40718b3fd707400416af', '13af09d9e8ad4da297e72e3020e290c8', '二、评级授信评价(15分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('13af09d9e8ad4da297e72e3020e290c8', '08c080e87e134183b239cc7409be5210', '信贷业务');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('08c080e87e134183b239cc7409be5210', 'd24e44cbc0c34452b1da93739adfe716', '控制活动(55%)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('d24e44cbc0c34452b1da93739adfe716', '0', '本部评价(70%)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('c46a67ffa5dc4cd990e9402dd5f21e56', '7540f5592a794ec0982bbea817d4b8ce', '一、组织结构评价(20分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('7d77b36468e04e96a56af4f105225fac', '7540f5592a794ec0982bbea817d4b8ce', '二、经营理念与风格评价(14分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('7540f5592a794ec0982bbea817d4b8ce', 'd24e44cbc0c34452b1da93739adfe716', '内部环境');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('15f1abe4b9544f7d900f6ccec9842256', '13af09d9e8ad4da297e72e3020e290c8', '一、信贷基础管理评价(10分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('73a60d0ed27c40718b3fd707400416af', '13af09d9e8ad4da297e72e3020e290c8', '二、评级授信评价(15分)');
insert into cs_intctl_assess_item_gather (ASSESS_ID, ASSESS_PARENT_ID, NAME)
values ('13af09d9e8ad4da297e72e3020e290c8', '08c080e87e134183b239cc7409be5210', '信贷业务');
1、通过普通的sql查询
查询 ASSESS_ID=0的所有子级,并返回查询的子级层级
SELECT DISTINCT
c1.LEVEL - 1 LEVEL,
c2.assess_id,
c2.assess_parent_id
FROM
(
SELECT
@ids AS _ids,
( SELECT @ids := GROUP_CONCAT( assess_id ) FROM cs_intctl_assess_item_gather WHERE FIND_IN_SET( assess_parent_id, @ids ) ) AS cids,
@l := @l + 1 AS LEVEL
FROM
cs_intctl_assess_item_gather,
( SELECT @ids := '0', @l := 0 ) b
WHERE
@ids IS NOT NULL
) c1,
cs_intctl_assess_item_gather c2
WHERE
FIND_IN_SET( c2.assess_id, c1._ids )
ORDER BY
LEVEL,
assess_id
-- 定义mysql函数
DROP FUNCTION IF EXISTS queryChildrenInfo;DELIMITER ;;
CREATE FUNCTION queryChildrenInfo(areaId INT)
RETURNS VARCHAR(4000)
BEGIN
DECLARE sTemp VARCHAR(4000);
DECLARE sTempChd VARCHAR(4000);
SET sTemp='$';
SET sTempChd = CAST(areaId AS CHAR);
WHILE sTempChd IS NOT NULL DO
SET sTemp= CONCAT(sTemp,',',sTempChd);
SELECT GROUP_CONCAT(assess_id) INTO sTempChd FROM CS_INTCTL_ASSESS_ITEM_GATHER WHERE FIND_IN_SET(assess_parent_id,sTempChd)>0;
END WHILE;
RETURN sTemp;
END;;
DELIMITER ;
-- 调用函数
SELECT DISTINCT assess_id,assess_parent_id FROM CS_INTCTL_ASSESS_ITEM_GATHER WHERE FIND_IN_SET(assess_id,queryChildrenInfo('0'))
https://blog.csdn.net/qq_26542493/article/details/107754967
mysql中从子类ID查询所有父类(做无限分类经常用到)
参考:https://www.cnblogs.com/biehongli/p/9391757.html
SELECT
T2.id,T2.parent_id,T2.name,T1.lvl
FROM
(SELECT @r := 7, @l := 0) vars, -- “7” 可以使用 #{regionId}
(SELECT
@r AS _id,
(SELECT
@r := parent_id
FROM
merchant_region
WHERE
id = _id -- 注意: 查询条件这里不要写@用户变量(试了好多,发现查询结果没什么固定的规律,这也可能是前面要写@r as _id的原因)
) AS parent_id,
@l := @l + 1 AS lvl
FROM
merchant_region h
WHERE
@r != 0
) T1
JOIN merchant_region T2 ON T1._id = T2.id
ORDER BY
T1.lvl DESC
<!-- 需求:区域和组织是多对多的关系,保存在organization_region中间表中,一个组织可以对应多个区域。 -->
<!--用户可以对应多个区域(多对多),保存在用户和区域的中间表merchant_user_region,区域之间存在层级关系 -->
<select id="selectRegionIdByOrganizationId" resultType="java.lang.Long">
SELECT
orr.region_id
FROM
organization_region orr
INNER JOIN (
SELECT
mr.id
FROM
(SELECT @ids := 0) b,
(
SELECT
@ids AS _ids,
(SELECT @ids := GROUP_CONCAT(id)
FROM merchant_region
WHERE FIND_IN_SET(parent_id, @ids)
) AS cids
FROM
merchant_region
WHERE
@ids IS NOT NULL) c1,
merchant_region mr
LEFT JOIN merchant_user_region mur ON mr.id = mur.merchant_region_id
where
FIND_IN_SET(mr.id, c1._ids)
AND mr.is_del = 0
AND mur.merchant_sub_user_id = #{merchantSubUserId}
ORDER BY mr.create_time DESC) mr ON mr.id = orr.region_id
WHERE
orr.organization_id = #{id}
</select>
–补充: 根据中间关系表筛选具有权限的数据
<select id="queryList" resultType="com.anbao.ambientMonitor.data.dto.device.DeviceInfoDTO">
SELECT
a.*
FROM
(
SELECT
d.id AS deviceId,
d.device_code,
d.device_model,
d.device_name,
d.online_status,
d.hardware_ver,
d.firmware_ver,
d.region_id,
d.last_communication_time,
d.bind_time
FROM
device d
LEFT JOIN merchant_region mr ON d.region_id = mr.id
LEFT JOIN merchant_user_region mur ON mr.id = mur.merchant_region_id
INNER JOIN (SELECT @ids := GROUP_CONCAT(mr.id) aaaa FROM merchant_region mr WHERE mr.merchant_id = #{params.merchantId}) a
WHERE
d.merchant_id = #{params.merchantId}
AND FIND_IN_SET(mur.merchant_region_id ,@ids)
AND d.is_del = 0
AND mur.merchant_sub_user_id = #{params.merchantSubUserId}
AND d.device_model = #{params.deviceModel}
UNION ALL
SELECT
d.id AS deviceId,
d.device_code,
d.device_model,
d.device_name,
d.online_status,
d.hardware_ver,
d.firmware_ver,
d.region_id,
d.last_communication_time,
d.bind_time
FROM
device d
WHERE
d.merchant_id = #{params.merchantId}
AND d.is_del = 0
AND d.device_model = #{params.deviceModel}
AND d.region_id IS NULL
) a
ORDER BY
a.bind_time DESC
</select>