现在有许多公司,每个公司又有许多部门,每个部门中可能还有子部门,子部门下面还可能有子部门,最终的那个部门下面是员工。每个员工对应数据库中的一条记录,该记录中有这个员工的照片。问题:如果查询指定公司的全部员工记录?如果查询指定的某部门的记录?问题关键:子部门下面可能还有子部门,层数不确定。就像一个文件夹里面还可以存在子文件夹一样。我的思路是:先创建一个树(treeView控件),每个接点表示一个机构。根结点是每个公司,每个公司下面有子结点表示部门,如果部门下还有子部门,就再建一个子结点。最终的那个子结点,对应的肯定是最小的一个机构,包含的人数最少。这么多公司当中,当我指定某公司(选中treeview某结点),就列出该公司所有员工。如果我指定的是公司下面的某部门,就只例出该部门的员工。 
现在的问题是:
     如何让记录与treeview关联起来?求较好的思路。--------------------------------
如果你没有思路,可以参考我的思路,觉得是否可行:
我想给数据库每条记录加一个备注字段,用备注字段逐级表示所选结点在树中的位置(由根结点逐级表示到)。点击某个结点,要实现查询到该结点所对应的机构中的记录。根据数据库中某个备注字段中的部分文字是否存在做为查询条件,比如现在有这样一个树:
  树                 (这个是行号便于后面叙述,实际不存在)
公司A                               1
   部门1                            2
   部门2                            3
     部门1                          4
     部门2                          5
         部门1                      6
   部门3                            7
公司B                               8
   部门1                            9
     部门1                          10
     部门2                          11
     部门3                          12
        部门1                       13
           部门2                    14
   部门2                            15
     部门1                          16
     部门2                          17
         部门1                      18
   部门3                            19
   
我点击第4行那个结点,备注字段就记住“公司A\部门2\部门1”,
我点击第14行那个结点,备注字段就记住“公司B\部门1\部门3\部门1\部门2”,
每条记录的备注字段都不允许为空。也就是说每个员工必须有所属的部门。当选择一个树时,得到树结点的绝对位置(从根结点表示),由位置构造一个字符串“×××\×××……\×××\”,根据数据库中某个备注字段中的部分文字是否存该字符串做为查询条件,于是我可以用备注字段与treeview关联起来了。这样做是否妥当? 还有没有其它方法?
 

解决方案 »

  1.   

    时间关系,楼主的思路我没仔细看,但之前我做过类似的东西,显示的思想就是递归,数据库设计时除了公司、部门除了本身的编号Id 外,还要有上级父ParentId,最上级的父ID就是自己;
    查询时用select * from 部门表where Left(ParentId, Length(所要查询部门ParentId)) = 所要查询部门ParentId
      

  2.   

    树型结构基本上就是按照ID,PARENTID这种双编号来做的,做成结构体,挂到TREEVIEW上,或用现成的控件!
    对于树型结构的查询(尤其是层次很深而且数据量很大,而且树型结构内的成员不是很活跃),这时就需要另创建一张表来记录关系了,这张表内可以表示出很直接的关系。类似于单编号法来做。
    这样就是双编号和单编号相结合来实现树型结构。
     
      

  3.   

    TREEVIEW挂上结构我知道,注释在删除的时候释放结构就可以了。不过我的问题是只用一个表来实现,已经解决,这里发贴只是希望求得更好的思路。
      

  4.   

    树的存储,有2种方式
    1、递归型:父节点id,本节点id,其它属性
    2、支撑型:根节点id(如果只有1个根,可以不要),本节点id,层次,序号,其它属性1、增删方便,生成树低效(需要递归,即使sql支持也是低效),树不会很大,可以一次性读入内存生成
    2、生成树高效,增删需要修改多条记录,适合树状论坛(读远大于写)
      

  5.   

    参考函数:
    procedure TfrmMain.CreateTree(sNode: TTreeNode );
    var
      s1: TTreeNode;
      node : TTreeNode;
      sql:string;
      PNode: PNodeData;
    begin
      FrmDm.AQDepartment.Close;
      FrmDm.AQDepartment.SQL.Clear;  if( sNode = nil ) then sql := '0'
      else sql :=   (PNodeData(sNode.Data)^).serial;  FrmDm.AQDepartment.SQL.Text := 'select * from Department where parent = '''+ sql +''' and IsDeleted <> ''1'' ';  FrmDm.AQDepartment.Open;
      FrmDm.AQDepartment.First;
      while not FrmDm.AQDepartment.Eof do
      begin
        New(PNode);
        if( sNode = nil ) then
        begin
          node := TreeView1.Items.Add(  sNode, FrmDm.AQDepartment.Fieldbyname( 'Name' ).AsString );
          node.ImageIndex := 0;
        end
        else
        begin
          node := TreeView1.Items.AddChild( sNode, FrmDm.AQDepartment.Fieldbyname( 'Name' ).AsString );
          node.ImageIndex := 1;
          node.SelectedIndex := 1;
        end;    PNode^.serial :=  FrmDm.AQDepartment.FieldByName( 'serial').AsString;
        node.Data := PNode;    FrmDm.AQDepartment.Next;
      end;
      FrmDm.AQDepartment.Close;
      if sNode = nil then
        s1 := TreeView1.Items.GetFirstNode
      else
       s1 := sNode.getFirstChild;  while s1<>nil do
      begin
        CreateTree(s1);
        s1 := s1.getNextSibling;
      end;  
    end
      

  6.   

    谢谢大家的回复,我是access数据库。
      

  7.   


      你可以建立两个额外字段,一个是标识节点类型,一个标识子部门ID,比如你选择A部门,判断出是部门节点,遍历找到A部门节点对应的所有子部门ID,再根据所选的子节点来筛选子部门ID
      表1
      节点类型 部门    子部门ID  ...
        1      A       01
        1      A       02
        1      A       03
        1      B       01
      表2
       部门    子部门   员工姓名    性别  照片  ..
        A       01    XXX       男    1.JPEG
        A       01     XXX      女    2.JPEG
       A        02    XXX       女    3.JPEG
    通过节点筛选生成SQL语句,然后显示
        
      

  8.   

    呵呵,楼上的方法还是用两个表,一个表不是也可以解决的嘛。用备注字段记录一个结点的绝对位置就可以了啊。请教一点,如果我的数据库中有8个字段,我用DBGrid只显示其中的7个字段,是不是没有办法实现?
      

  9.   

    01         // IT部
    0101       // 程序部
    010101     // 程序部一组
    0102       // 网络部
    010201     // 网络部一组
    010202     // 网络部二组
    01020101
    02
    0201
    020101
    020102读前面的,如网络部 select * from tableA where id like '0102%'  // 后面加百分号
      

  10.   


    dbgrid显示时,把那个字段设为不显示就行了。也可以在sql里不取那个字段。另外,我在9楼说的就是思路啊
      

  11.   

    对,15楼的方法就是我所用的方法,只不过我是用汉字来表示的,更直观。并且存在ACCESS数据库每条记录的备注字段中。
      

  12.   

    基本上都是采用这种方法的。我们的ERP也是这样的。
      

  13.   

    我认为,应该多加2个字段比较好。
    一个是ParentID,一个是OwnerID,
    上级节点ID,和归属ID。
    归属的意思就是 员工归部门,部门归公司。
    pID,用来建立树枝结构,oID用来你选择某个部门的时候,直接用这个字段过滤出所有员工。特例,
    公司A                              1 
      部门1                            2 
      部门2                            3 
        部门1                          4 
        部门2                          5 
    公司A(1) 有部门2(3),部门下有 (4),(5)
    那么
    3的ParentID=1ID  OwnerID=1ID
    4的ParentID=3ID  OwnerID=1ID
    5的ParentID=3ID  OwnerID=1ID理解?
      

  14.   

    设计成两个表,部门一个表,加上部门ID,上级部门ID,递归取部门,员工一个表,加上部门ID,关联查询
      

  15.   


    这种方式有个问题,我们公司的ERP就是这样做:当查询时 like%01%,%02%,输出是什么,不好
    不能只用数字,最好加上字符什么的
      

  16.   

       部门ID   名称    图片  上级ID
     
       0       总部     空    -1
       1       下部     空    0 
       -1       人员     有图  1   这样就可以了。 我觉得这样是最合理的 根据-1判断是否是人员
       
       
      

  17.   

    为了一劳永逸 建立个标准   写个treeview  有 DataSource, datafield ,keyfield,parentfield  keyfield和parentfield组合 产生树,datafield用来显示书中文本
      不复杂。~
      

  18.   

    一个部门(部门ID,父部门ID)表,
    一个成员(成员ID)表,
    一个部门成员(部门ID,成员ID)表
      

  19.   

    我写了个DBtreeview , parentid,fieldsname,keyid, dataset 等几个属性,   
      

  20.   

    部门ID    上级部门ID
    01         null
    0101       01
    010101     0101
    02         null
    ...
    基本就是这样。前台生成树的时候,直接order by 部门ID,一次循环搞定,不用递归。