多维度多级数据查询sql语句

数据结构

实体A配置权限时,有以下维度:

多维度多级数据查询sql语句_第1张图片

产品线数据有:查询接口测试一级产品类别、查询接口测试二级产品类别、查询接口测试三级产品类别

服务网点数据有:查询接口测试网点1、查询接口测试网点2、查询接口测试网点3

部门数据有(负责人维度):查询接口测试上级部门、查询接口测试下级部门

以上数据都有上下级关系

用户“张三”的基础信息中,部门是查询接口测试上级部门,服务网点是查询接口测试网点2,产品线是查询接口测试一级产品类别

实体A数据表如下:

id name owningbusinessunit ptest_workstation ptest_productline
1 实体1 查询接口测试上级部门
2 实体2 查询接口测试下级部门
3 实体3 查询接口测试网点1
4 实体4 查询接口测试网点2
5 实体5 查询接口测试网点3
6 实体6 一级产品类别
7 实体7 二级产品类别
8 实体8 三级产品类别

配置“张三”三个维度的权限都为“本部门及下级部门”,读权限举例:

可查询到一级、二级、三级产品类别的数据,即上表中的6、7、8

可查询到测试网点2、测试网点3的数据,即上表中的4、5

可查询到上级部门、下级部门的数据,即上表中的1、2

(因为几个维度的权限走的是并集,所以上表中,空白字段不论填什么值,都不影响读权限举例的逻辑)

sql断言

思路一

三个维度一起查询,sql会很长,不便于理解,所以拆分开,每个维度都查询一下count(*),查询后汇总,跟接口返回的totalcount对比是否一致

WITH RECURSIVE DepartmentHierarchy AS (
    -- 锚点成员:从部门A开始
    SELECT new_srv_stationid
    FROM new_srv_station
    WHERE new_srv_stationid  = (select new_stationid from systemuser where domainname = 'zhangsan') -- 假设通过部门名称定位部门A

    UNION ALL

    -- 递归成员:找到下级部门
    SELECT d.new_srv_stationid
    FROM new_srv_station d
    INNER JOIN DepartmentHierarchy dh ON d.new_superiorstation_id = dh.new_srv_stationid
)
-- 查询部门A及其下级部门的所有订单
SELECT  o.ptest_duoweiduid 
FROM ptest_duoweidu o
JOIN DepartmentHierarchy dh ON o.ptest_workstation = dh.new_srv_stationid;
WITH RECURSIVE DepartmentHierarchy AS (
    -- 锚点成员:从部门A开始
    SELECT businessunitid
    FROM businessunit
    WHERE businessunitid  = (select businessunitid from systemuser where domainname = 'zhangsan') -- 假设通过部门名称定位部门A

    UNION ALL

    -- 递归成员:找到下级部门
    SELECT d.businessunitid
    FROM businessunit d
    INNER JOIN DepartmentHierarchy dh ON d.parentbusinessunitid = dh.businessunitid
)
-- 查询部门A及其下级部门的所有订单
SELECT o.ptest_duoweiduid 
FROM ptest_duoweidu o
JOIN DepartmentHierarchy dh ON o.owningbusinessunit = dh.businessunitid;

WITH RECURSIVE DepartmentHierarchy AS (
    -- 锚点成员:从部门A开始
    SELECT new_productgroupid
    FROM new_productgroup
    WHERE new_productgroupid  in (select new_productgroupid from new_productgroupusers where systemuseridname = '张三') -- 假设通过部门名称定位部门A

    UNION ALL

    -- 递归成员:找到下级部门
    SELECT d.new_productgroupid
    FROM new_productgroup d
    INNER JOIN DepartmentHierarchy dh ON d.new_parentgroup_id = dh.new_productgroupid
)
-- 查询部门A及其下级部门的所有订单
SELECT o.ptest_duoweiduid 
FROM ptest_duoweidu o
JOIN DepartmentHierarchy dh ON o.ptest_productline = dh.new_productgroupid;

用这种方法断言,最后确实数据对得上,但是其实是错误的, 增加几条实体A的数据:

id name owningbusinessunit ptest_workstation ptest_productline
1 实体1 查询接口测试上级部门
2 实体2 查询接口测试下级部门
3 实体3 查询接口测试网点1
4 实体4 查询接口测试网点2
5 实体5 查询接口测试网点3
6 实体6 一级产品类别
7 实体7 二级产品类别
8 实体8 三级产品类别
9 实体9 查询接口测试上级部门 查询接口测试网点2
10 实体10 查询接口测试上级部门 一级产品类别
11 实体11 查询接口测试网点3 二级产品类别

三种维度查询

负责人维度:查询count=4,实际为实体1、2、9、10

服务网点维度:查询count=4,实际为实体4、5、9、11

产品线维度:查询count=5,实际为实体6、7、8、10、11

汇总count=13,实际接口返回的totalcount=10

分析发现,业务数据实体9、10、11都重复计算了一次,导致汇总count多了3,所以分开汇总count不可取,没办法去重

思路二

三个维度的查询出业务数据的id,汇总id后再去重,最后再计数:

WITH RECURSIVE DepartmentHierarchy1 AS (
    -- 第一个递归查询:基于new_srv_station
    SELECT new_srv_stationid
    FROM new_srv_station
    WHERE new_srv_stationid = (SELECT new_stationid FROM systemuser WHERE domainname = 'zhangsan')
    UNION ALL
    SELECT d.new_srv_stationid
    FROM new_srv_station d
    INNER JOIN DepartmentHierarchy1 dh ON d.new_superiorstation_id = dh.new_srv_stationid
),
DepartmentHierarchy2 AS (
    -- 第二个递归查询:基于businessunit
    SELECT businessunitid
    FROM businessunit
    WHERE businessunitid = (SELECT businessunitid FROM systemuser WHERE domainname = 'zhangsan')
    UNION ALL
    SELECT d.businessunitid
    FROM businessunit d
    INNER JOIN DepartmentHierarchy2 dh ON d.parentbusinessunitid = dh.businessunitid
),
DepartmentHierarchy3 AS (
    -- 第三个递归查询:基于new_productgroup
    SELECT new_productgroupid
    FROM new_productgroup
    WHERE new_productgroupid IN (
        SELECT new_productgroupid FROM new_productgroupusers WHERE systemuseridname = '张三'
    )
    UNION ALL
    SELECT d.new_productgroupid
    FROM new_productgroup d
    INNER JOIN DepartmentHierarchy3 dh ON d.new_parentgroup_id = dh.new_productgroupid
),
-- 汇总查询结果并去重
Uniqueptest_duoweiduids AS (
    SELECT o.ptest_duoweiduid
    FROM ptest_duoweidu o
    JOIN DepartmentHierarchy1 dh1 ON o.ptest_workstation = dh1.new_srv_stationid

    UNION

    SELECT o.ptest_duoweiduid
    FROM ptest_duoweidu o
    JOIN DepartmentHierarchy2 dh2 ON o.owningbusinessunit = dh2.businessunitid

    UNION

    SELECT o.ptest_duoweiduid
    FROM ptest_duoweidu o
    JOIN DepartmentHierarchy3 dh3 ON o.ptest_productline = dh3.new_productgroupid
)
-- 计算非重复的ptest_duoweiduid的数量
SELECT COUNT(DISTINCT ptest_duoweiduid) AS unique_count
FROM Uniqueptest_duoweiduids;

再优化下结构:

WITH RECURSIVE UserValues AS (
    SELECT 
        new_stationid, 
        businessunitid, 
        new_productgroupid
    FROM systemuser
    WHERE domainname = 'zhangsan'
),
DepartmentHierarchy AS (
    -- 锚点成员:从部门A开始
    SELECT 'station' AS type, new_srv_stationid AS id
    FROM new_srv_station
    WHERE new_srv_stationid = (SELECT new_stationid FROM UserValues)

    UNION ALL

    SELECT 'station' AS type, d.new_srv_stationid
    FROM new_srv_station d
    INNER JOIN DepartmentHierarchy dh ON d.new_superiorstation_id = dh.id

    UNION ALL

    SELECT 'businessunit' AS type, businessunitid AS id
    FROM businessunit
    WHERE businessunitid = (SELECT businessunitid FROM UserValues)

    UNION ALL

    SELECT 'businessunit' AS type, d.businessunitid
    FROM businessunit d
    INNER JOIN DepartmentHierarchy dh ON d.parentbusinessunitid = dh.id

    UNION ALL

    SELECT 'productgroup' AS type, new_productgroupid AS id
    FROM new_productgroup
    WHERE new_productgroupid IN (SELECT new_productgroupid FROM new_productgroupusers WHERE systemuseridname = '张三')

    UNION ALL

    SELECT 'productgroup' AS type, d.new_productgroupid
    FROM new_productgroup d
    INNER JOIN DepartmentHierarchy dh ON d.new_parentgroup_id = dh.id
),
Uniqueptest_duoweiduids AS (
    SELECT o.ptest_duoweiduid
    FROM ptest_duoweidu o
    JOIN DepartmentHierarchy dh ON (
        (dh.type = 'station' AND o.ptest_workstation = dh.id) OR
        (dh.type = 'businessunit' AND o.owningbusinessunit = dh.id) OR
        (dh.type = 'productgroup' AND o.ptest_productline = dh.id)
    )
)
SELECT COUNT(DISTINCT ptest_duoweiduid) AS unique_count
FROM Uniqueptest_duoweiduids;

以上方法查询出的数据可以和接口返回的totalcount对上

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