企业层级父子充电站权限管控及统计方案与数据库表结构咨询
层级站点权限管控与站点数量统计技术方案
一、层级站点权限管控实现
1. 所属子公司集合查询
公司表为典型的邻接表树形结构,首先需要获取当前登录用户所属公司的所有下属子公司ID集合:
- MySQL 8.0+、PostgreSQL等支持递归CTE的数据库,直接用如下语句查询:
WITH RECURSIVE company_hierarchy AS ( -- 根节点为当前用户所属公司ID SELECT id FROM Company WHERE id = :current_user_company_id UNION ALL SELECT c.id FROM Company c INNER JOIN company_hierarchy ch ON c.parent_company_id = ch.id ) SELECT id FROM company_hierarchy;
- 不支持CTE的低版本数据库,可通过代码递归遍历或者存储过程实现子公司ID集合查询。
2. 权限拦截与查询过滤
- 用户登录成功后,将查询到的可访问公司ID集合存入缓存(如Redis),缓存过期时间可设置为1~2小时,公司层级变动时主动失效对应缓存降低数据库压力。
- 所有站点相关的查询接口,自动追加
company_id IN (:accessible_company_ids)过滤条件,保证用户只能访问所属公司及下属子公司的站点数据。 - 新增全局权限拦截器,针对单站点查询、修改等操作,提前校验目标站点的
company_id是否在当前用户的可访问范围内,避免越权操作。
二、层级站点数量统计实现
根据数据量和性能要求,可选择以下三种方案:
1. 实时递归统计(适用数据量<10万的场景)
直接通过递归CTE关联站点表完成统计,无需额外存储和维护成本,实时性最高:
WITH RECURSIVE company_hierarchy AS ( SELECT id, name FROM Company WHERE id = :target_company_id UNION ALL SELECT c.id, c.name FROM Company c INNER JOIN company_hierarchy ch ON c.parent_company_id = ch.id ) SELECT COUNT(s.id) AS total_station_count FROM company_hierarchy ch LEFT JOIN Station s ON s.company_id = ch.id;
2. 闭包表优化(适用中大规模数据、查询频繁的场景)
新增公司关系闭包表company_closure,字段为ancestor_id(祖先公司ID)、descendant_id(后代公司ID)、depth(层级差),存储所有公司的祖先后代映射关系:
- 公司新增、层级关系变更时同步维护闭包表数据,维护成本远低于递归查询开销。
- 统计时直接关联闭包表即可,查询性能提升10倍以上:
SELECT COUNT(s.id) AS total_station_count FROM company_closure cc LEFT JOIN Station s ON s.company_id = cc.descendant_id WHERE cc.ancestor_id = :target_company_id;
3. 预计算缓存(适用超大规模数据、性能要求极高的场景)
新增公司站点统计表company_station_stat,字段为company_id、total_station_count、update_time:
- 触发更新时机:站点新增/删除/所属公司变更时、公司层级关系调整时,递归更新对应公司及其所有上级公司的统计值。
- 查询时直接读取统计表数据,响应速度可达毫秒级。
三、边界场景处理
- 顶级母公司
parent_company_id可设置为0或NULL,作为递归查询的终止条件。 - 公司删除、站点迁移时,同步更新关联的缓存、闭包表、统计表数据,避免统计结果异常。
- 跨集团隔离:如果存在多个独立集团,权限校验时需额外判断公司所属集团,避免跨集团越权访问。
内容的提问来源于stack exchange,提问作者Huzoor Bux
相关产品推荐
相关产品推荐

