获取treeview节点的父节点

时间:2018-12-23 23:36:43

标签: delphi firebird

firebird数据库中存储着“帐户”表:

Acc_id-唯一,整数,不为null,主键,
Acc_num-唯一,varchar(30)
Prnt_id-整数
Acc_Title-说明,文本说明

 Acc_id   Acc_num   Prnt_id   Acc_Title

  0       Base       Null     Base account  
  1       1000       0        Current assets account
  2       1100       1        some text    
  3       1110       2        some text
  4       1110 1     3        some text
  5       1110 1 15  4        some text
  6       2000       0        some text
  7       2700       6        some text
  8       1110 1 16  4        some text
  ...
  101     1155 1     1155     some text
  102     1125       1100     some text

例如,我必须在db中插入帐户2700的记录。在编辑控件中,我输入帐号2700,并且必须确定其父级为帐户2000(parent_id = 6)。 如何使用firebird-sql找出帐户2000是帐户2700的父级或1120是1125等的父级?

如果我错误继续使用1000或1100或1110帐户并要创建帐户1125,则 sql查询必须猜测父帐户是帐户1100,并且必须将其添加为1100帐户的子帐户< / strong>,而不是1000或1110。

enter image description here

2 个答案:

答案 0 :(得分:0)

接下来您再不告诉您有关您的问题的信息。您必须将表格中的样本数据显示为简短的摘要!因此,我们只能尝试猜测您的意思,如果我们猜错了,那就倒霉了。

  • 假设(猜测)“ 1200”之类的值存储在VARCHARTitle中-而不是存储在Acc_number中,
  • 假设标题是唯一的(如果您未在该UNIQUE CONSTRAINT字段上使用UNIQUE INDEXTitle来丰富SQL表,则标题可能不是唯一的,
  • 假设该字段上有一个index(否则会很慢),并且acc_id字段和parent_id字段上都有一个

    您的查询如下所示:

    Select t1.* 
    from MyTable t1, MyTable t2 
    where t2.parent_id = t1.acc_id
      and t2.title = :TitleParameter 
    

    根据所使用的Delphi DB访问库(还有很多https://github.com/petdance/bobby-tables/issues/98),代码将如下所示:

    Var qGetParent: TSqlQuery;
    
    .....
    
    begin
      if nil = qGetParent then begin
         qGetParent := TSqlQuery.Create( MySQLConnection );
         qGetParent.SQL.Text := 'select...'; // see above
         qGetParent.Prepared := true;        // make SQL server compile this query only once
      end;
    
      qGetParent.Params[0].AsString := '1200'; 
        // we only have one parameter, so somewhat slow .ParamByName can easily be skipped  
    
      qGetParent.Open;
      while not qGetParent.EOF do begin
        // listing 0 or 1 or many rows returned by the query
    
    
        qGetParent.Next;
      end;
      qGetParent.Close; 
    end;
    

    当然,很难理解为什么您需要这样的查询。您在哪里采用“ 1200”格式?从一个程序。但是该程序(如屏幕快照中的树一样)已经知道为标题为acc_id的行设置了哪个1200值!您已经在程序中包含有关树的数据。

答案 1 :(得分:0)

因此,您需要猜测哪个节点最适合作为父节点?好吧:

with recursive a (n) as (
  select cast(:N as varchar(30)) from rdb$database
  union all
  select
    case
      when n containing ' ' then left(n,char_length(n)-position(' ',reverse(n)))
      when char_length(n)=1 then 'Base'
      else left(n,char_length(n)-1)
    end
  from a
  where char_length(n)>=1 and n<>'Base')
select ac.acc_id,ac.acc_number
from a
  join accounts ac on ac.acc_number=rpad(a.n,4,'0')
fetch first 1 row only