delphi SQL+TreeView递归如何生成BOM树?(求高人)

torch_pym 2012-09-28 05:10:55
新手求教:新建一个窗体,拖一个edit,button,输入001016133,如何用递归生成BOM树?
以下是测试数据,delphi SQL+TreeView递归如何生成BOM树?(求高人)

CREATE TABLE [dbo].[tb_bom](
[Parn_litm] [nvarchar](50) NOT NULL,
[Itemno] [nvarchar](50) NULL,
[Chld_litm] [nvarchar](50) NOT NULL,
[Qty] [dbo].[dtQuantity] NOT NULL
) ON [PRIMARY]

insert into tb_bom values( '001016133', '001', 'X40004A10ZN', '2.0000' )
insert into tb_bom values( '001016133', '002', 'X91026A10ZN', '3.0000' )
insert into tb_bom values( '001016133', '003', 'X91035A10ZN1', '1.0000' )
insert into tb_bom values( '001016133', '004', 'A99060A10ZN', '1.0000' )
insert into tb_bom values( '001016133', '005', 'X22010A10NI', '1.0000' )
insert into tb_bom values( '001016133', '006', 'X39000A', '1.0000' )
insert into tb_bom values( '001016133', '007', 'S32008A00CU', '1.0000' )
insert into tb_bom values( '001016133', '008', 'X91027A12ZN', '1.0000' )
insert into tb_bom values( '001016133', '009', 'M30504D10NI', '1.0000' )
insert into tb_bom values( '001016133', '010', 'X99085A', '2.0000' )
insert into tb_bom values( '001016133', '011', 'A10895A10NI', '1.0000' )
insert into tb_bom values( '001016133', '012', 'M60289A10NI', '1.0000' )
insert into tb_bom values( '001016133', '013', 'X33112A10NI', '3.0000' )
insert into tb_bom values( '001016133', '014', 'S12329K00016', '1.0000' )
insert into tb_bom values( '001016133', '015', 'Y8001VO130', '1.0000' )
insert into tb_bom values( '001016133', '016', 'Y00005A', '1.0000' )
insert into tb_bom values( '001016133', '017', 'Y50005A', '1.0000' )
insert into tb_bom values( '001016133', '018', 'Y10010A', '1.0000' )
insert into tb_bom values( '001016133', '019', 'Y30001A', '1.0000' )
insert into tb_bom values( '001016133', '020', 'BBA001016133', '1.0000' )
insert into tb_bom values( '001016133', '021', 'BCA001016133', '12.0000')
...全文
480 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
haitao 2012-10-09
  • 打赏
  • 举报
回复
节点不能全部动态生成?
是指多次sql了?

18楼的代码好像也没防止死循环(互为父节点)的地方?
haitao 2012-10-08
  • 打赏
  • 举报
回复
with cte as
(
select *,1 flevel from @t where [Parn_litm]='001000333'
union all
select b.*,a.flevel+1 from cte a
join @t b on a.[Chld_litm]=b.[Parn_litm]
--where [Parn_litm]=
)
select * from cte
haitao 2012-10-08
  • 打赏
  • 举报
回复
带节点"+"号?treeview的节点前"+"号是自动出现的,如果它有子节点

想得到带层次信息的记录?
torch_pym 2012-10-08
  • 打赏
  • 举报
回复
感谢sz_haitao使用SQL CTE,如果转换为delphi语句,用递归如何生成带节点"+"号的BOM树?感谢!
haitao 2012-10-08
  • 打赏
  • 举报
回复

declare @t TABLE (
[Parn_litm] [nvarchar](50) NOT NULL,
[Chld_litm] [nvarchar](50) NOT NULL,
[Qty] [nvarchar](50) NOT NULL
);

insert into @t values( '001000333', 'X22641A00NI', '1.0000' )
insert into @t values( 'X22641A00NI', 'X22641C00NI', '1.0000' )
insert into @t values( 'X22641A00NI', 'X39005A10NI', '1.0000' )
insert into @t values( 'X22641C00NI', 'X22641C00RW', '1.0000' )
insert into @t values( 'X39005A10NI', 'X39005A10RW', '1.0000' )
insert into @t values( '101000333', 'X22641A00NI', '1.0000' )


select * from @t;

with cte as
(
select * from @t where [Parn_litm]='001000333'
union all
select b.* from cte a
join @t b on a.[Chld_litm]=b.[Parn_litm]
)
select * from cte
torch_pym 2012-10-08
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
仔细看了一下你的表结构,感觉有点特别
一般层次表的结构都是:id,parn_id两个字段(本节点,父节点)即可构建树形
你的除了itemno,Parn_litm,还有一个子节点(Chld_litm)字段?

另外,事例记录也尚未体现多级的关系。。。。
[/Quote]

对不起各位大侠:可能是我没有表达清楚,上面的整合记录可忽略,请以下面5笔数据为例,parn_litm为主节点,chld_litm为子节点,诚请各位大侠指点迷津,delphi+TreeView,在edit1输入'001016133',在treeview中用递归生成并展开bom表?以下为测试数据,小弟求各位指导求教:


CREATE TABLE [dbo].[tb_bom](
[Parn_litm] [nvarchar](50) NOT NULL,
[Chld_litm] [nvarchar](50) NOT NULL,
[Qty] [nvarchar](50) NOT NULL
) ON [PRIMARY]

insert into tb_bom values( '001000333', 'X22641A00NI', '1.0000' )
insert into tb_bom values( 'X22641A00NI', 'X22641C00NI', '1.0000' )
insert into tb_bom values( 'X22641A00NI', 'X39005A10NI', '1.0000' )
insert into tb_bom values( 'X22641C00NI', 'X22641C00RW', '1.0000' )
insert into tb_bom values( 'X39005A10NI', 'X39005A10RW', '1.0000' )
torch_pym 2012-10-08
  • 打赏
  • 举报
回复
先结帐,重新发贴求教!
kaikai_kk 2012-10-08
  • 打赏
  • 举报
回复
用with cte as语法
torch_pym 2012-10-08
  • 打赏
  • 举报
回复
经测试,加上您上面这段代码与不加效果差不多,唯一不足的是,节点不能全部动态生成:
如原图:


procedure Treceiving_slip_frm.CreateTree;
procedure LoadTree(Pre:string;preNode:TTreeNode);
var
pInfo:PTNodeInfo;
node:TTreeNode;
sql:string;
i:integer;
Query:TADOQUery;
begin
Application.ProcessMessages;
Query:=TADOQuery.Create(nil);
Query.ConnectionString:=sys_datamoudle_Frm.adoq_connect.ConnectionString;
sql:= Format('select parn_litm,chld_litm from bom_loc where parn_litm=%s', [QuotedStr(pre)]);
Query.Close;
Query.SQL.Clear;
Query.SQL.Add(sql);
Query.Open;
Query.First;
while not Query.Eof do
begin
{for i:=0 to treeview1.items.count-1 do
if PTNodeInfo(treeview1.items[i].data).chld_litm=Query.Fields[1].AsString then
begin
query.next;
continue;
end; }
try
new(pInfo);
pInfo.parn_litm:=Query.Fields[0].AsString;
pInfo.chld_litm:=Query.Fields[1].AsString;
node:=treeview1.Items.AddChild(preNode,pInfo.parn_litm);
node.Data:=pInfo;
Application.ProcessMessages;
loadTree(pInfo.chld_litm,node);
Query.Next;
finally
Query.Close;
Query.Free;
end;
end;
end;
begin
if treeview1.HasParent then
begin
treeview1.Items.Clear;
treeview1.Items.BeginUpdate;
LoadTree(Edit1.text,nil);
treeview1.FullExpand;
treeview1.Items.EndUpdate;
end;
end;
haitao 2012-10-08
  • 打赏
  • 举报
回复
for i:=0 to tv.items.count-1 do
if PTNodeInfo(tv.items[i].data).chld_litm:=Query.Fields[1].AsString then
begin
query.next;
continue;
end;
然后:
try
new(pInfo);
pInfo.parn_litm:=Query.Fields[0].AsString;
pInfo.chld_litm:=Query.Fields[1].AsString;
torch_pym 2012-10-08
  • 打赏
  • 举报
回复
数据确定没有问题,我加了句 if pInfo.parn_litm=pInfo.chld_litm then但似乎依然解决不了问题,不知道是何原因。
haitao 2012-10-08
  • 打赏
  • 举报
回复
你这种是第3种了:递归发sql
我说的方法2是它的优化版本,sql只需要发一次

如果死循环了,可能是数据有问题
可以在.AddChild前扫描现有的树节点,是否已经有它了,有则不再添加
torch_pym 2012-10-08
  • 打赏
  • 举报
回复
To sz_haitao,貌似有这个效果。根据您提供的思路,我想用以下的方法,节点是可以动态生成了,但是好像有死循环,敬请再次帮忙查看代码,谢谢。以下是我写的递归过程,请指教!


type
PTNodeInfo=^TNodeInfo;
TNodeInfo=record
parn_litm,chld_litm:string;
end;


procedure Treceiving_slip_frm.CreateTree;
procedure LoadTree(Pre:string;preNode:TTreeNode);
var
pInfo:PTNodeInfo;
node:TTreeNode;
sql:string;
Query:TADOQUery;
begin
Query:=TADOQuery.Create(nil);
Query.ConnectionString:=sys_datamoudle_Frm.adoq_connect.ConnectionString;
sql:= Format('select parn_litm,chld_litm from bom_loc where parn_litm=%s', [QuotedStr(pre)]);
Query.Close;
Query.SQL.Clear;
Query.SQL.Add(sql);
Query.Open;
ShowMessage(Query.SQL.Text);
Query.First;
while not Query.Eof do
begin
try
new(pInfo);
pInfo.parn_litm:=Query.Fields[0].AsString;
pInfo.chld_litm:=Query.Fields[1].AsString;
node:=treeview1.Items.AddChild(preNode,pInfo.parn_litm);
node.Data:=pInfo;
loadTree(pInfo.parn_litm,node);
Query.Next;
finally
Query.Close;
Query.Free;
end;
end;
end;
begin
LoadTree(Edit1.text,nil);
treeview1.FullExpand;
end;


procedure Treceiving_slip_frm.Button1Click(Sender: TObject);
var
T:dword;
begin
inherited;
lab_dt.Caption := Format('createTree所用时间: %d ms', [GetTickCount - T]);
//调用递归
CreateTree;
end;
haitao 2012-10-08
  • 打赏
  • 举报
回复
ln:=$d$a;
{adoquery}q.sql.text:=
'with cte as'
+ln+'('
+ln+'select *,1 flevel,cast([Chld_litm] as nvarchar(4000)) fo from @t where [Parn_litm]='+quotedstr(edit1.text)
+ln+'union all'
+ln+'select b.*,a.flevel+1,fo+''\''+b.[Chld_litm] from cte a '
+ln+'join @t b on a.[Chld_litm]=b.[Parn_litm]'
+ln+')'
+ln+'select * from cte'
+ln+'order by fo';
q.open;
s:='';
while not q.eof do
begin
s:=s+stringofchar(' ',q.fieldbyname('flevel').asinteger-1)+q.fieldbyname('Chld_litm').asstring
q.next;
end;

然后让treeview.loadfromstream(stringstream{s});就是完整的树了
torch_pym 2012-10-08
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]
带节点"+"号?treeview的节点前"+"号是自动出现的,如果它有子节点

想得到带层次信息的记录?
[/Quote]
To sz_haitao:不是用SQL CTE生成并展开BOM表,而是用delphi+treeview控件+edit1控件,使用delphi递归过程调用,生成以下的界面,我这里只有数据,没有代码,想尝试生成如附图的效果的BOM表展
开效果,敬请指教!如下图,如解决,另开贴给分或加分,小弟新手,求教!

haitao 2012-10-07
  • 打赏
  • 举报
回复
仔细看了一下你的表结构,感觉有点特别
一般层次表的结构都是:id,parn_id两个字段(本节点,父节点)即可构建树形
你的除了itemno,Parn_litm,还有一个子节点(Chld_litm)字段?

另外,事例记录也尚未体现多级的关系。。。。
torch_pym 2012-10-07
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
2种做法:
1、sql就使用cte(sql2005开始支持)先递归得到完整的子树
2、全部可能相关的记录加载到本地内存记录集,程序反复循环扫描内存记录集生成完整的子树
[/Quote]
To sz_haitao高人,能否delphi+TreeView,edit输入'001016133',在treeview中生成bom?本人是新手,对递归理解不是很透,求教?分不够,可加,谢谢!
haitao 2012-10-07
  • 打赏
  • 举报
回复
2种做法:
1、sql就使用cte(sql2005开始支持)先递归得到完整的子树
2、全部可能相关的记录加载到本地内存记录集,程序反复循环扫描内存记录集生成完整的子树
torch_pym 2012-10-07
  • 打赏
  • 举报
回复
求高人?
torch_pym 2012-09-28
  • 打赏
  • 举报
回复
更正:
 

[Qty] [dbo].[dtQuantity] NOT NULL
以上[dbo].[dtQuantity]为自定义类型,可直接为[Qty] [nvarchar](50) NOT NULL,

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧