有两个这样的有,其中一张表是用来保存学生信息,叫材料信息表(ID,name)分别代表材料号和材料名称。
另一个表是这样的(ID1,ID2,COUNT),ID1表示材料1,ID2表示材料2,COUNT为材料1包含材料2的个数 。
ID1 ID2 COUNT
4001 4002 2
4001 4003 3
4001 4004 4
4002 4005 5
4002 4006 2
上图说明了,材料4001由2个4002构成、3个4003构成、4个4004构成。材料4002由5个4005构成、2个4006构成。
就是说4001由4002构成,而4002又由4005构成,4005又可能还有其下级构成。
现在我想查出材料4001的全部构造情况,这应该涉及到递归过程,请问这样的递归该如何写呢?
小弟不盛感激!!!!!如能给出具体代码更好!
另一个表是这样的(ID1,ID2,COUNT),ID1表示材料1,ID2表示材料2,COUNT为材料1包含材料2的个数 。
ID1 ID2 COUNT
4001 4002 2
4001 4003 3
4001 4004 4
4002 4005 5
4002 4006 2
上图说明了,材料4001由2个4002构成、3个4003构成、4个4004构成。材料4002由5个4005构成、2个4006构成。
就是说4001由4002构成,而4002又由4005构成,4005又可能还有其下级构成。
现在我想查出材料4001的全部构造情况,这应该涉及到递归过程,请问这样的递归该如何写呢?
小弟不盛感激!!!!!如能给出具体代码更好!
create proc abc
@id1 varchar(20)
As
declare @layer int
begin create table #temptable(
Id1 varchar(20) null,
Id2 varchar(20) null,
Level1 int null,
[count] int default 0,
) set @layer = 0
insert into #temptable select id1,id2,@layer,[Count] from 你的表 where id1=@id1
while (@@RowCount>0)
begin
Set @Layer=@Layer+1
insert into #TempTable
select @id1,a.id2,@layer,b.[count]*a.[Count] from 你的表 a join #TempTable b
on a.id1=b.id2 where b.level1=@layer-1
end
select @id1,id2,sum([count]) from #tempTable group by id2
Drop Table #TempTable
end
http://www.sundyn.com/floor.jpg和楼主的问题性质差不多,可以看看。
根据level1也就是层数递增排序(这样就保证了将要键的节点的父节点已经建立好了,就是这个道理)
然后循环纪录集在treeview上建树下面的是递归建树的方法不建议用
库里需要一条有总结点的纪录
‘全部节点' '产品1'
调用
BuildBomTree(‘全部节点',nil,Treeview1);
procedure TFrm_Pro_BomTree.BuildBomTree(AId: string; ParentNode: TTreeNode;
temp_treeview: Ttreeview);
var
QryTmp: TADOQuery;
myNode: TTreeNode;
myLabel: TLabel;
begin
QryTmp := TADOQuery.Create(nil);
qrytmp.connection := Dm_Main.Database_Cs;
QryTmp.SQL.Add('select * from pro_bom');
QryTmp.SQL.Add('where cp_peij_no=:AId');
qrytmp.Parameters.ParamByName('aid').value := aid;
QryTmp.Open;
while not QryTmp.Eof do
begin
myNode := temp_Treeview.Items.AddChild(ParentNode, QryTmp.fieldbyname('wl_peij_no').AsString + ':' +
Dm_Pro_Shuju.Return_PeiJMc(QryTmp.fieldbyname('wl_peij_no').AsString));
//ReturnNodeText(QryTmp.fieldbyname('wl_peij_no').AsString));这句不用了
//创建标签,caption存放各分支的AutoId表识
myLabel := TLabel.Create(Application);
myLabel.Visible := False;
myLabel.Caption := QryTmp.fieldbyname('wl_peij_no').AsString;
myNode.Data := myLabel;
BuildBomTree(QryTmp.fieldbyname('wl_peij_no').Asstring, myNode, temp_treeview); //递归用过程
QryTmp.Next;
end;
QryTmp.Free;
end;
--那么直接按递增排序然后按我下面写的建树过程的其中一部分套用就行--如果编码没有规律那么只能按层排序后建树
--以下的就是,当然也适合编码有规律的情况
--我用存储过程返回按层排序的数据集
--创建测试表
create table t_test(
sParent varchar(20),
sChild varchar(20),
iCount int
constraint Pk_t_test primary key(sParent,sChild) )
--插入测试数据
insert into t_test select 'A','B',2
union select 'A','C',3
union select 'C','D',2
union select 'C','E',4--创建"返回按层排序数据集"的存储过程
create proc p_sort(@sParent varchar(20))
as
begin
declare @l int --记录层
create table #t( --返回按层排序数据集
sParent varchar(20),
sChild varchar(20),
L int not null default(0),
primary key (sParent,sChild))
set @l = 0
insert into #t select '',@sParent,@l
while @@rowcount > 0
begin
set @l=@l+1
insert into #t select b.sChild,a.sChild,@l
from t_test a inner join #t b on a.sParent=b.sChild
where L=@l-1
end
select * from #t order by L
return 0
end--调用存储过程
exec p_sort 'A' --返回按层排序数据集
/*测试结果
sParent sChild L
-------------------- -------------------- -----------
A 0
A B 1
A C 1
C D 2
C E 2(所影响的行数为 5 行)*///delphi程序实现
//窗体上放 button1,adoconnection1, ADOStoredProc1,TreeView1
//ADOStoredProc1的connection连接 adoconnection1
//button1的点击事件里写
procedure TForm1.Button1Click(Sender: TObject);
function MakeTree(sParent:String):Boolean;
var
nodeCur:TTreeNode;
sPrt,sCld:String;
begin
nodeCur:=nil;
with ADOStoredProc1 do
try
Close;
ProcedureName:= 'p_sort;1';
Parameters.Refresh;
Parameters.ParamByName('@sParent').Value:=sParent;
Open;
if Parameters.ParamByName('@return_value').Value<>0 then Abort;
First;
while not eof do
begin
sPrt:=FieldByName('sParent').AsString;
sCld:=FieldByName('sChild').AsString;
if sPrt='' then nodeCur:=TreeView1.Items.AddChild(nil,sCld)
else
begin
while nodeCur.Text<>sPrt do
nodeCur:=nodeCur.Parent;
nodeCur:=TreeView1.Items.AddChild(nodeCur,sCld);
end;
Next;
end;
except
showmessage('出错!');
raise;
end;
result:= true;
end;
begin
TreeView1.Items.Clear;
TreeView1.Items.BeginUpdate;
MakeTree('A');
TreeView1.Items.EndUpdate ;
TreeView1.FullExpand;
end;
包含 Transact-SQL 语句或批处理的 Unicode 字符串,stmt 必须是可以隐式转换为 ntext 的 Unicode 常量或变量。不允许使用更复杂的 Unicode 表达式(例如使用 + 运算符串联两个字符串)。不允许使用字符常量。如果指定常量,则必须使用 N 作为前缀。例如,Unicode 常量 N'sp_who' 是有效的
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Db, ADODB;type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
function parts_stru (x_id:string):string;implementation{$R *.DFM}function parts_stru (x_id:string):string;
var qr_temp:TADOquery;
x_name:string;
s:string;
begin
s:='';
qr_temp:=TADOquery.create(nil);
qr_temp.Connection :=form1.ADOConnection1 ;
with qr_temp do
begin
close;
sql.clear;
sql.Add('select * from table2');
sql.add('where id=:id');
parameters[0].value:=x_id;
open;
if not isempty then
x_name:=fieldbyname('name').asString
else
begin
showmessage('不存在此材料');
form1.close;
end;
close;
sql.clear;
sql.add('select * from table1');
sql.add('where id1=:id1');
parameters[0].value:=x_id;
open;
if not isempty then
begin
first;
while not eof do
begin
s:=s+fieldbyname('count').asString+'*('+parts_stru(fieldbyname('id2').asString)+')+';
next;
end;
result:=copy(s,1,length(s)-1);
end
else
result:=trim(x_name);
end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
edit1.Text :=parts_stru('4001');
end;end.
記得給我分:)
请查收。
sParent sChild L
-------------------- -------------------- -----------
A 0
A B 1
A C 1
B D 2 -----把C改为B
B E 2 -----把C改为B
读到第三条记录时,nodecur.text为C,那么你在读第四条记录时,根据你的程序好像不会把D、E读到B节点下面。
“把C改为B”是什么意思
临时表里存放的节点就是用ADOStoredProc1建树的那个例子的节点sChild字段的父节点就是t_test表的父节点,存放在临时表的sParent字段
--插入测试数据
insert into t_test select 'A','B',2
union select 'A','C',3
union select 'B','D',2
union select 'B','E',4
如果你把临时表t_test改成上面形式,就会出错,不信你自己试一下。