如何基于最低层级构建公司人员筛选查询并过滤冗余层级
解决方案:过滤冗余层级选择,保留最低层级项
核心逻辑是:移除所有被更具体选择项覆盖的父层级项——如果一个选择项是另一个更长选择项的前缀(即存在子层级的选择),则这个父层级项可以被忽略,只保留最具体的子层级项。
预处理步骤
- 按层级深度降序排序:将所有选择项按数组长度从长到短排序,确保先处理最具体的(层级最低的)项。
- 跟踪已覆盖的前缀:维护一个集合记录已经被更具体项覆盖的前缀,遍历排序后的项时,若当前项不在已覆盖集合中,则保留它,并将它的所有前缀加入集合,后续遇到这些前缀的项直接跳过。
PHP代码实现
// 示例输入数据 $selections = [ ["group2"], ["group2", "unit11", "department50", "team10"], ["group2", "unit11", "department50", "team58"], ["group2", "unit10"], ["group5", "unit23"], ["group5", "unit23", "department101"] ]; // 步骤1:按数组长度降序排序 usort($selections, function($a, $b) { return count($b) - count($a); }); // 步骤2:过滤冗余项 $coveredPrefixes = []; $filteredSelections = []; foreach ($selections as $selection) { // 将当前选择项转为唯一字符串,用于判断是否已被覆盖 $selectionStr = implode('|', $selection); if (!in_array($selectionStr, $coveredPrefixes)) { $filteredSelections[] = $selection; // 生成当前项的所有前缀,加入覆盖集合 $prefix = []; foreach ($selection as $item) { $prefix[] = $item; $coveredPrefixes[] = implode('|', $prefix); } } } // 输出过滤后的结果 print_r($filteredSelections);
代码说明
- 排序后优先处理最长的项(最具体的层级),确保先标记它们的所有父级前缀为已覆盖状态。
- 用
implode('|', $selection)将数组转为唯一字符串,简化集合内的存在性判断。 - 每保留一个项,就把它的所有层级前缀(比如team项对应的department、unit、group级前缀)加入覆盖集合,后续遇到这些前缀的项直接跳过。
适配查询构造器
过滤完成后,用$filteredSelections构建查询即可避免冗余的OR条件:
foreach ($filteredSelections as $selection) { $fullQuery->orWhere(function($query) use ($selection) { // 按层级映射数据库字段,假设selection顺序为group、unit、department、team $fields = ['group', 'unit', 'department', 'team']; foreach ($selection as $index => $value) { $query->where($fields[$index], '=', $value); } }); }
内容的提问来源于stack exchange,提问作者pileup
相关产品推荐
相关产品推荐

