一张表table
字段为:id,parentid,name,用它可递归生成一棵树。
但是我现在想得到某一节点下的全部叶子,这个select语句怎么写?
假设我知道id='aaa'这个节点,我想得到以这个节点为根节点的全部叶子,注:
我只知道得到一棵树的全部叶子是这样写的:
select * from table where id not in (select parentid from table)  
另外,所谓叶子就是最终节点,也就是没有儿子的节点。
我用的是access数据库。

解决方案 »

  1.   

    http://expert.csdn.net/Expert/TopicView1.asp?id=2259840有一个DBTREE 中有DEMO,虽然写得简单了一点,但还是可以的。
      

  2.   

    我也同意:单一sql无法解决。如果树的层次很深,单是sql语句是无法实现的。可以使用存储过程来实现。不过access不支持存储过程。那只好通过递归查询的函数来实现了。单条sql语句没办法的。其实也没有必要非得用一条sql来实现啊,办法还多的是。
      

  3.   

    如果表中的ID是有位数区分的,那就好办,否则,若树有多层,那就没法实现,只能自己做程序了。
    你的表属于哪种情况。把什么都用SQL语句来实现,也并不是解决问题的好方法!
      

  4.   

    select * from table A where (parentid like 'aaa%') and (id not in select * from table B where B.parentid = A.id )
      

  5.   

    这条语句应该可以吧,你试一试。
    有两个条件:
    1. 这些 id 的 parentid 是 'aaa'
    2. 这些 id 不作为 parentidSELECT * 
    FROM table 
    WHERE (parentid='aaa') and 
      (id not in (SELECT parentid
                  FROM table))
      

  6.   

    算法是有的。不过要是单独的写sql语句这样执行速度可能慢了点。
    提供另一种方法:此方法节点的级数必先定好。
    就是更改数据表的结构。用户的资产类别是这样做的。
    表结构如下
    name,id,parentid,parentid1,parentid2,parentid3
    ..............................................
    这样的话每条记录都有id,父亲的id,祖父的id...
    要实现你讲的功能也就容易了。
      

  7.   

    一条SQL应该是实现不了的吧。
    除非子节点是你节点的值加某一个部分内容。
    如:父节点:10
        子节点:1001
        孙节点:100101
        。。
    建议:
    如果你现在的设计,建议一级一级的填啊。
    先填完第一级,再填第一级的所有子节点的节点。
    或者是展开时动态检测。
      

  8.   

    这是我的写好的代码,你可以看一看,实现的功能是差不多的,只不过数据库的结构上有一点不一样:procedure TDepartmentForm.TreeNodeSet();
    var
      Node_Root,node_parent : TTreeNode;
      str_sql1 : string;
      str_parent1 : string;
    begin
      treeview1.Items.Clear;
      Node_Root := treeview1.Items.AddChild(nil,'**'+datamodule1.CompanyName);
      node_parent := Node_Root;
      str_sql1:='select deptid +'+ '''--''' + '+ deptname as fieldcurrent,deptinid as fieldparent ' +
              ' from department ' +
              ' where accountid =''' + datamodule1.ZhangTao +'''';
      str_parent1:=' parentid = ''*''';
      Addtreenode(DataModule1.ADOConnection1,treeview1,node_parent,str_sql1,str_parent1);
      Treeview1.Select(Node_Root);
      TreeView1Click(self);
    end;procedure Addtreenode(ADOConnection1 : TADOConnection ;treeview1 : TTreeview ; node_parent : TTreeNode ; str_sql : string ; str_parent : string);
    {
    str_sql format :
         select deptid + '--' + deptname as fieldcurrent,deptinid as fieldparent
         from department
         [where accountid='0001']
         只能有两个字段,前一字段为本级字段,后一字段为父级字段
    str_parent format :
         若str_sql含有"UNION"字符串则:
                 要用 where parentinid = 'parent_id' (where 父级字段 =<字符串>) 或者 and parentinid = 'parent_id' (and 父级字段 =<字符串>)
                 否则用:     parentinid = 'parent_id'(父级字段 =<字符串>)
    }
    var
        i : integer;
        str_parenttmp : string;
        str_sqlparamtmp: string;
        node_tmp : TTreeNode;
        ADOdatasettmp : TADODataSet;
    begin
        if (pos('WHERE',uppercase(str_sql)) = 0) and (pos('UNION',uppercase(str_sql)) = 0) then
            str_sqlparamtmp := str_sql + ' where ' + str_parent
        else
        if  (pos('WHERE',uppercase(str_sql)) <> 0) and (pos('UNION',uppercase(str_sql)) = 0) then
            str_sqlparamtmp := str_sql + ' and ' + str_parent
        else
            str_sqlparamtmp := str_sql + str_parent;                                                           try
        ADOdatasettmp := TADODataSet.Create(nil);
        ADOdatasettmp.Connection := ADOConnection1;
        with ADODataSettmp do
        begin
          //CommandText :='select deptid,deptname,deptinid from department where accountid=''' + datamodule1.zhangtao + ''' and parentid='''+ str_parent +'''';
          CommandText := str_sqlparamtmp;
          Open;
          if RecordCount = 0 then
          begin
              Close;
              Free;
              exit;
          end;      First;
          for i := 1 to RecordCount do
          begin
            str_parenttmp := copy(str_parent,1,pos('=',str_parent)) + '''' + string(Fields[1].Value) + '''';
            node_tmp := treeview1.Items.AddChild(node_parent, string(ADOdatasettmp.Fields[0].Value));
            Addtreenode(ADOConnection1,treeview1,node_tmp,str_sql,str_parenttmp);
            Next;
          end;
          Close;
          Free;
        end; //with
          ADOdatasettmp:=nil;
    except
        ADOdatasettmp.Close;
        ADOdatasettmp.Free;
        ADOdatasettmp:=nil;
        showmessage(str_sqlparamtmp);
    end;
    end;
      

  9.   

    一下,首先你的数据库的结构对你treeview的操作和不利,这个方面我写过贴子,暂时找不到了。
      

  10.   

    俗话说:解铃还需系铃人你既然用了递归生成树,为什么不用递归来查呢???用单独的SQL实现有难度且速度可能是最大的问题!!
      

  11.   

    id,parentid,name,用它可递归生成一棵树。
    但是我现在想得到某一节点下的全部叶子,这个select语句怎么写?
    假设我知道id='aaa'这个节点,我想得到以这个节点为根节点的全部叶子,注:
    我只知道得到一棵树的全部叶子是这样写的:
    select * from table where id not in (select parentid from table)  
    另外,所谓叶子就是最终节点,也就是没有儿子的节点。
    我用的是access数据库。
    ---------------------------------------------------------------------
    用parentid 保存当前节点的父亲节点,想得到以这个节点为根节点的全部儿子节点:
    select * from table where parentid='aaa'
      

  12.   

    先生成TreeView,在通过TreeView来查询不就简单多了~~
      

  13.   

    楼主生成树的方法与我曾经设计的程序是一样的hiflower(花) 的方法应该是非常正确的。
      

  14.   

    这是我回答别人问题的一个存储过程,就是你想要的
    create table table1(id char(3),parentid char(3),name char(10))
    insert into table1 values('1','0','化工原料')
    insert into table1 values('2','1','氨类')
    insert into table1 values('3','1','脂类')
    insert into table1 values('4','2','乙氨酸')create procedure showtree
    @id char(3),--要展开的节点
    @no int  --层次,传入为1,以后递增。这是存储过程的关键,就是逐层查找子节点
    as
    begin
    if @no=1
       select @no as cno,table1.* into #temp from table1 where parentid=@id
         --如果@no为1,则表示搜索第一层数据,并建立临时表,加入结果数据
    declare @tid char(3)
    declare temp_sear cursor for select id from #temp where cno=@no 
    open temp_sear
    fetch next from temp_sear into @tid
    while @@FETCH_STATUS=0
    begin
      set @no=@no+1
      insert into #temp select @no as cno,table1.* from table1 where parentid=@tid
      fetch next from temp_sear into @tid
    end 
    close temp_sear
    DEALLOCATE temp_sear
    if @no<32  --最深为32层
       if (select count(*) from #temp where cno=@no)>0 
       exec showtree '',@NO  --此处进行递归
    end
    select id,parentid,name from #temp order by id
    go
      

  15.   

    不好意思,楼主(小妹?),上次就是回答你的问题,ACCESS不支持存储过程,搞不定。