部门管理中非递归搜索部门以及所管辖下部门,处理此种问题包括以下几种方法:
一、树形控件显示,当展开部门节点时,再去读取所管辖的子部门。
二、SQL SERVER后台写函数处理,利用游标处理。
三、使用父部门ID、层次级别实现部门搜索。
本文重点介绍,利用父部门ID、层次级别实现部门搜索。
搜索部门时,首先使用用户登录,获取到用户所属部门ID和LevelPath;
组合LevelPath+A部门IDA(简称组合串),再使用like %组合串% 搜索此部门的下属部门。
LevelPath级别路径:记录上级以上所有路径(包含上级,不含本级)。格式:A组ID1A-A组ID2A-A组ID3A,比如:A1A-A2A-A3A
Department
-------------------------------------------------------------------------------
DepetID/GroupID GroupName LevelPath ParentGroupID
-------------------------------------------------------------------------------
1 整个系统
2 公司 A1A 1
3 部门A A1A-A2A 2
4 部门B A1A-A2A 2
5 部门A子部门a A1A-A2A-A3A 3
6 部门A子部门b A1A-A2A-A3A 3
7 部门A子部门a组 A1A-A2A-A3A-A5A 5
-------------------------------------------------------------------------------
DepetID/GroupID:自动增长字段
部门级别路径类:
LevelPath.h
/*
部门级别路径类,方便非递归搜索部门以及管辖部门。
搜索部门时,首先使用用户登录,获取到用户所属部门ID和LevelPath;
组合LevelPath+A部门IDA(简称组合串),再使用like %组合串% 搜索此部门的下属部门。
LevelPath级别路径:记录上级以上所有路径(包含上级,不含本级)。格式:A组ID1A-A组ID2A-A组ID3A,比如:A1A-A2A-A3A
*/
#pragma once
class LevelPath
{
public:
LevelPath();
~LevelPath();
//设置参数
void SetParams(char cPrev,char cNext,char cSplit);
//组转换到单个级别路径
char * GroupId2CellLevelPath(int nGroupId);
//单个级别路径转换到组
int CellLevelPath2GroupId(char *pCellLevelPath);
//组合级别路径
bool MergeLevelPath(char *pPrevLevelPath,char *pNextLevelPath,char *pCurrentLevelPath,char *pNewLevelPath);
bool MergeLevelPath(int arrayLevelPath[],int nLevelPathSize,char *pNewLevelPath);
//解析级别路径
int ParseLevelPath(char *pLevelPath,int arrayLevelPath[],int & nLevelPathSize);
protected:
char m_cPrev; //前字符
char m_cNext; //后字符
char m_cSplit; //分隔符
};
LevelPath.cpp
#include "LevelPath.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
LevelPath::LevelPath()
{
m_cPrev = 'A'; //前字符
m_cNext = 'A'; //后字符
m_cSplit = '-'; //分隔符
}
LevelPath::~LevelPath()
{
}
//设置参数
void LevelPath::SetParams(char cPrev,char cNext,char cSplit)
{
m_cPrev = cPrev;
m_cNext = cNext;
m_cSplit = cSplit;
}
//组转换到单个级别路径
char * LevelPath::GroupId2CellLevelPath(int nGroupId)
{
char szPath[256] = {0};
sprintf(szPath,"%c%d%c",m_cPrev,nGroupId,m_cNext);
return szPath;
}
//单个级别路径转换到组
int LevelPath::CellLevelPath2GroupId(char *pCellLevelPath)
{
if(NULL == pCellLevelPath)
return 0;
int nGroupId = 0;
char szTmp[256] = {0};
//查找最后字符
char *p = strrchr(pCellLevelPath,m_cNext);
if(p != NULL)
{
memcpy(szTmp,pCellLevelPath,p-pCellLevelPath);
}
else
{
strcpy(szTmp,pCellLevelPath);
}
//查找前字符
p = strchr(szTmp,m_cPrev);
if(p != NULL)
{
nGroupId = atoi(szTmp+1);
}
return nGroupId;
}
//组合级别路径
bool LevelPath::MergeLevelPath(char *pPrevLevelPath,char *pNextLevelPath,char *pCurrentLevelPath,char *pNewLevelPath)
{
if(NULL == pNewLevelPath || NULL == pCurrentLevelPath)
return false;
if(NULL != pPrevLevelPath && strlen(pPrevLevelPath) > 0)
{
sprintf(pNewLevelPath,"%s%c%s",pPrevLevelPath,m_cSplit,pCurrentLevelPath);
if(NULL != pNextLevelPath && strlen(pNextLevelPath) > 0)
{
char szTmp[32] = {0};
sprintf(szTmp,"%c",m_cSplit);
strcat(pNewLevelPath,szTmp);
strcat(pNewLevelPath,pNextLevelPath);
}
}
else
{
sprintf(pNewLevelPath,"%s",pCurrentLevelPath);
if(NULL != pNextLevelPath && strlen(pNextLevelPath) > 0)
{
char szTmp[32] = {0};
sprintf(szTmp,"%c",m_cSplit);
strcat(pNewLevelPath,szTmp);
strcat(pNewLevelPath,pNextLevelPath);
}
}
return true;
}
bool LevelPath::MergeLevelPath(int arrayLevelPath[],int nLevelPathSize,char *pNewLevelPath)
{
if(nLevelPathSize <= 0 || NULL == pNewLevelPath)
return false;
int m = 0;
for(m=0; m<nLevelPathSize; m++)
{
strcat(pNewLevelPath,GroupId2CellLevelPath(arrayLevelPath[m]));
if(m != nLevelPathSize-1)
{
//非最后一个levelpath时,增加分隔符
sprintf(pNewLevelPath,"%s%c",pNewLevelPath,m_cSplit);
}
}
return true;
}
/*
功能说明:解析级别路径
参数说明:pLevelPath,分组级别路径字符串;arrayLevelPath,表示组ID数组
返回值:int 0,表示成功,-1,表示参数错误;-2,表示nLevelPathSize太小
*/
int LevelPath::ParseLevelPath(char *pLevelPath,int arrayLevelPath[],int & nLevelPathSize)
{
if(nLevelPathSize <= 0 || NULL == pLevelPath)
return -1;
char *p = NULL,*q = NULL;
char szCell[128] = {0};
int n = 0;
q = pLevelPath;
while(true)
{
memset(szCell,0,sizeof(szCell));
p = strchr(q,m_cSplit);
if(p != NULL)
{
memcpy(szCell,q,p-q);
if(n >= nLevelPathSize)
{
return -2;
}
arrayLevelPath[n] = CellLevelPath2GroupId(szCell);
n++;
q = p + 1;
continue;
}
else
{
strcpy(szCell,q);
if(n >= nLevelPathSize)
{
return -2;
}
arrayLevelPath[n] = CellLevelPath2GroupId(szCell);
n++;
break;
}
}
nLevelPathSize = n;
return 0;
}
使用方法:
1、 插入部门
void insertDepartment(int nGroupID,char *pGroupLevelPath,char *pInsertGroupName)
{
LevelPath lpLevelPath;
char szParentLevelPath[256] = {0};
char szParentParentLevelPath[256] = {0};
char szNewLevelPath[256] = {0};
strcpy(szParentLevelPath, lpLevelPath.GroupId2CellLevelPath(nGroupID));
strcpy(szParentParentLevelPath,pGroupLevelPath);
lpLevelPath.MergeLevelPath(szParentParentLevelPath,NULL,szParentLevelPath,szNewLevelPath);
//插入sql语句
char szSql[1024] = {0};
sprintf(szSql,” Insert into Department(GroupName,LevelPath,ParentGroupID) values(‘%s’,’%s’,%d)”, pInsertGroupName, szNewLevelPath, nGroupID);
执行sql语句
}
2、 更新部门
参考插入部门代码。
3、 删除部门
void deleteDepartment(int nGroupID)
{
LevelPath lpLevelPath;
char szGroupLevelPath [256] = {0};
strcpy(szGroupLevelPath, lpLevelPath.GroupId2CellLevelPath(nGroupID));
//插入sql语句
char szSql[1024] = {0};
sprintf(szSql,"DELETE FROM Department WHERE GroupID=%d OR levelPath like '%%%s%%')",nGroupID,szGroupLevelPath);
执行sql语句
}
4、 搜索部门以及管辖部门
void queryDepartment(int nGroupID)
{
LevelPath lpLevelPath;
char szGroupLevelPath [256] = {0};
strcpy(szGroupLevelPath, lpLevelPath.GroupId2CellLevelPath(nGroupID));
//插入sql语句
char szSql[1024] = {0};
sprintf(szSql,"SELECT GroupID,GroupName ,ParentGroupID,LevelPath FROM Department WHERE GroupID=%d OR levelPath like '%%%s%%')",nGroupID,szGroupLevelPath);
执行sql语句
}