当@n=6时,原始数据如下:
a b
----------- -----------
1 1
2 3
3 5
4 7
5 9
6 11
7 2
8 4
9 6
10 8
11 10
12 12第1条记录 b=1 查找a=1的记录 还是第1条记录 构成一个环,输出
id c
1 1
第2条记录 b=2 查找a=2的记录,第3条a=3 b=5
查找a=5 的记录,第5条a=5 b=9
查找a=9 的记录,第9条a=9 b=6
...
查找a=7 的记录,第7条a=7 b=2
又回到了2 加上前面的输出
id c
1 1
2 2,3,5,9,6,11,10,8,4,7
.....
a b
----------- -----------
1 1
2 3
3 5
4 7
5 9
6 11
7 2
8 4
9 6
10 8
11 10
12 12第1条记录 b=1 查找a=1的记录 还是第1条记录 构成一个环,输出
id c
1 1
第2条记录 b=2 查找a=2的记录,第3条a=3 b=5
查找a=5 的记录,第5条a=5 b=9
查找a=9 的记录,第9条a=9 b=6
...
查找a=7 的记录,第7条a=7 b=2
又回到了2 加上前面的输出
id c
1 1
2 2,3,5,9,6,11,10,8,4,7
.....
-----
第2条记录 a=2 b=3 查找a=3的记录,第3条a=3 b=5
create table t(a int,b int)
declare @n int
set @n = 4
declare @i int
select @i = 1
while @i <=2*@n
begin
insert t select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
end
update t set b = 2*@n -1 where b = 0
update t set b = 2*@n where a = 2*@n
select * from t*/declare @T table(ID int,col nvarchar(1000))
declare @i int,@j int
set @i=1
while @i!>4
begin
select @j=b from T where a=@i
if @i=1
insert @T values(@i,@j)
else if @i=2
insert @t values(@i,rtrim(@i)+','+rtrim(@j))
else if @i=3
begin
select @j=b from T where a=@i+1
insert @t values(@i,rtrim(@i+1)+','+rtrim(@j))
end
else
begin
select top 1 @j=b from T order by b desc
insert @t values(@i,rtrim(@j)+','+rtrim(@j))
end
set @j=(select b from t where a=@j)
while @j<>@i and not exists(select 1 from @T where ID=@i and charindex(','+rtrim(@j)+',',','+col+',')>0)
begin
--print rtrim(@i)+'i'
print @j
update a
set col=a.col+','+rtrim(@j)
from
@T a
where
a.ID=@i
set @j=(select b from t where a=@j)
end
set @i=@i+1endselect * from @t
--生成测试数据
create table BOM(a int,b int )go
declare @n int
set @n = 5
declare @i int
select @i = 1
while @i <=2*@n
begin
insert BOM select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
end
update BOM set b = 2*@n -1 where b = 0
update BOM set b = 2*@n where a = 2*@n
select * from BOM
/*a b
----------- -----------
1 1
2 3
3 5
4 7
5 9
6 2
7 4
8 6
9 8
10 10(所影响的行数为 10 行)
*/go--创建用户定义函数,每个子节点de父节点的信息
create function f_getChild(@ID int)
returns varchar(100)
as
begin
declare @i int
declare @oldid int
declare @ret varchar(100)
set @oldid = @id
declare @t table(ID VARCHAR(10),PID VARCHAR(10),Level INT)
set @i = 1
insert into @t select a,b,@i from BOM where A = @ID
while @@rowcount<>0
begin
set @i = @i + 1
insert into @t
select
a.a,a.b,@i
from
BOM a,@t b
where
a.b=b.ID and b.Level = @i-1 and a.a <> @oldid
end
select @ret=','+rtrim(id)+isnull(@ret,'')
from @t order by level
set @ret=stuff(@ret,1,1,'')
select @ret = @ret + '--' + min(id) from @t
return @ret
end
go--执行查询
select a,substring(c,1,charindex( '--',c)-1) as c
from (
select a,isnull(dbo.f_getchild(a),'') as c
from bom) T
where a = substring(c,charindex('--',c)+2,100)
go
--输出结果
/*
a c
----------- -----------------------
1 1
2 3,5,9,8,6,2
4 7,4
10 10(所影响的行数为 4 行)
*/--删除测试数据
drop function f_getChild
drop table BOM
go
/*
create table t(a int,b int)
declare @n int
set @n = 4
declare @i int
select @i = 1
while @i <=2*@n
begin
insert t select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
end
update t set b = 2*@n -1 where b = 0
update t set b = 2*@n where a = 2*@n
select * from t*/declare @T table(ID int,col nvarchar(1000))
declare @i int,@j int
set @i=1
while @i!>4
begin
select @j=b from T where a=@i
if @i=1
insert @T values(@i,@j)
else if @i=2
insert @t values(@i,rtrim(@i)+','+rtrim(@j))
else if @i=3
begin
select @j=b from T where a=@i+1
insert @t values(@i,rtrim(@i+1)+','+rtrim(@j))
end
else
begin
select top 1 @j=b from T order by b desc
insert @t values(@i,rtrim(@j)+','+rtrim(@j))
end
set @j=(select b from t where a=@j)
while @j<>@i and not exists(select 1 from @T where ID=@i and charindex(','+rtrim(@j)+',',','+col+',')>0)
begin
--print rtrim(@i)+'i'
-- print @j
update a
set col=a.col+','+rtrim(@j)
from
@T a
where
a.ID=@i
set @j=(select b from t where a=@j)
end
set @i=@i+1endselect * from @t
--结果:
/*
1 1
2 2,3,5
3 4,7,6
4 8,8
*/--原始数据
/*
create table t(a int,b int)
declare @n int
set @n = 5
declare @i int
select @i = 1
while @i <=2*@n
begin
insert t select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
end
update t set b = 2*@n -1 where b = 0
update t set b = 2*@n where a = 2*@n
select * from t*/--结果
/*
1 1
2 2,3,5,9,8,6
3 4,7
4 10,10
*/
declare @t table(a int,b int)
declare @n int
set @n = 6
declare @i int
select @i = 1while @i <=2*@n
begin
insert @t select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
endupdate @t set b = 2*@n -1 where b = 0
update @t set b = 2*@n where a = 2*@n
select * from @tdeclare @r table(b int,path varchar(1000))
declare @curA int,@curB int,@cur int,@s varchar(1000),@tmpB int,@inner bit,@thisB int
select @cur=max(a),@i=0 from @tset @inner = 1
while @inner = 1 and (select count(*) from @r)<@n
begin
set @curB = null
select top 1 @curB = b from @t a where b not in(select b from @r) if @curB is null
set @inner = 0
else begin
select @i = 0,@thisB = @curB
select @s=null,@tmpB=@curB,@s=@curB while @i<@cur
begin
select @curA=b.a,@curB=b.b from @t b
inner join @t a
on a.b=b.a
where a.b=@tmpB
select @s=@s + ',' + rtrim(@curB)
if @thisB = @curB
begin
set @i=100000
insert @r select @curB,@s
end
else
select @i=@i+1,@tmpB = @curB
end
end
endselect * from @r
/*
1 1,1
3 3,5,9,6,11,10,8,4,7,2,3
5 5,9,6,11,10,8,4,7,2,3,5
7 7,2,3,5,9,6,11,10,8,4,7
9 9,6,11,10,8,4,7,2,3,5,9
11 11,10,8,4,7,2,3,5,9,6,11
2 2,3,5,9,6,11,10,8,4,7,2
4 4,7,2,3,5,9,6,11,10,8,4
6 6,11,10,8,4,7,2,3,5,9,6
8 8,4,7,2,3,5,9,6,11,10,8
10 10,8,4,7,2,3,5,9,6,11,10*/
declare @t table(a int,b int)
declare @n int
set @n = 6
declare @i int
select @i = 1while @i <=2*@n
begin
insert @t select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
endupdate @t set b = 2*@n -1 where b = 0
update @t set b = 2*@n where a = 2*@n
select * from @tdeclare @r table(b int,path varchar(1000))
declare @curA int,@curB int,@cur int,@s varchar(1000),@tmpB int,@inner bit,@thisB int
select @cur=max(a),@i=0 from @tset @inner = 1
while @inner = 1 --and (select count(*) from @r)<@n
begin
set @curB = null
select top 1 @curB = b from @t a where b not in(select b from @r) if @curB is null
set @inner = 0
else begin
select @i = 0,@thisB = @curB
select @tmpB=@curB,@s=null while @i<@cur
begin
select @curA=b.a,@curB=b.b from @t b
inner join @t a
on a.b=b.a
where a.b=@tmpB
select @s=isnull(@s+',','') + rtrim(@curA)
if @thisB = @curB
begin
set @i=100000
insert @r select @curB,@s
end
else
select @i=@i+1,@tmpB = @curB
end
end
endselect * from @r order by b
/*
1 1
2 2,3,5,9,6,11,10,8,4,7
3 3,5,9,6,11,10,8,4,7,2
4 4,7,2,3,5,9,6,11,10,8
5 5,9,6,11,10,8,4,7,2,3
6 6,11,10,8,4,7,2,3,5,9
7 7,2,3,5,9,6,11,10,8,4
8 8,4,7,2,3,5,9,6,11,10
9 9,6,11,10,8,4,7,2,3,5
10 10,8,4,7,2,3,5,9,6,11
11 11,10,8,4,7,2,3,5,9,6
12 12
*/
create table BOM(a int,b int )go
declare @n int
set @n = 5
declare @i int
select @i = 1
while @i <=2*@n
begin
insert BOM select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
end
update BOM set b = 2*@n -1 where b = 0
update BOM set b = 2*@n where a = 2*@n
select * from BOM
/*a b
----------- -----------
1 1
2 3
3 5
4 7
5 9
6 2
7 4
8 6
9 8
10 10(所影响的行数为 10 行)
*/go--创建用户定义函数,每个子节点de父节点的信息
create function f_getChild(@ID int)
returns varchar(100)
as
begin
declare @i int
declare @oldid int
declare @ret varchar(100)
set @oldid = @id
declare @t table(ID VARCHAR(10),PID VARCHAR(10),Level INT)
set @i = 1
insert into @t select a,b,@i from BOM where A = @ID
while @@rowcount<>0
begin
set @i = @i + 1
insert into @t
select
a.a,a.b,@i
from
BOM a,@t b
where
a.b=b.ID and b.Level = @i-1 and a.a <> @oldid
end
select @ret=','+rtrim(id)+isnull(@ret,'')
from @t order by level
set @ret=stuff(@ret,1,1,'')
select @ret = @ret + '--' + min(id) from @t
return @ret
end
go--执行查询
select a,substring(c,1,charindex( '--',c)-1) as c into #
from (
select a,isnull(dbo.f_getchild(a),'') as c
from bom) T
where a = substring(c,charindex('--',c)+2,100)select a=(select count(1)+ 1 from # where a <d.a),c
from # d
go
--输出结果
/*
a c
----------- -----------------------
1 1
2 3,5,9,8,6,2
3 7,4
4 10(所影响的行数为 4 行)
*/--删除测试数据
drop function f_getChild
drop table BOM,#
go
to happyflystone : 结果顺序不对,第一个数字应该为最小的。
2 3,5,9,8,6,2 应为:2,3,5,9,8,6
3 7,4 应为:4,7to roy_88 :n为不固定的。to fcuandy :差之毫厘,失之千里,关键就在这。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 4 时,结果:1,2,12
上面的都不能,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 4 时,结果:1,2,12
上面的都不能,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 4 时,结果:1,2,12
上面的都不能,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 4 时,结果:1,2,12
上面的都不能,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 4 时,结果:1,2,12
上面的都不能,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 4 时,结果:1,2,12
上面的都不难,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 6 时,结果:1,2,12
上面的都不难,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 6 时,结果:1,2,12
上面的都不难,难就难在有一个条件,只给了一个@n,并没有给数据表。
而且@n = 1亿,现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 6 时,结果:1,2,12现在我们明白,给定一个@n,就能得到一个串,而且只要@n相同,串就相同,@n不同,串可能相同,也可能不同,
与其它因素,只要@n给定了,就能得到一个串。
上面的都不难,
现在的问题是,只给了一个@n,并没有给数据表,而且@n = 1亿,求这个串,
现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 6 时,结果:1,2,12现在我们明白,给定一个@n,就能得到一个串,而且只要@n相同,串就相同,@n不同,也不同,与其它因素,只要@n给定了,就能得到一个串。
上面的都不难,
现在的问题是,只给了一个@n,并没有给数据表,而且@n = 1亿,求这个串,
现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
在set @oldid = @id前面加一句
select @id = a from bom where b =@id就可以了。
问题的第二步是,只要求显示一个串,这个串由结果集中C字段的首个数字构成。
例如:
当@n = 4 时,结果:1,2,4,8
当@n = 5 时,结果:1,2,4,10
当@n = 6 时,结果:1,2,12现在我们明白,给定一个@n,就能得到一个串,而且只要@n相同,串就相同,@n不同,串也不同,与其它因素,只要@n给定了,就能得到一个串。
上面的都不难,
现在的问题是,只给了一个@n,并没有给数据表,而且@n = 1亿,求这个串,
现在不太可能通过创建表来计算数据了。有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
有结果立即结贴,分不够,另开贴加分。
create table BOM(a int,b int )go
declare @n int
set @n = 4
declare @i int
select @i = 1
while @i <=2*@n
begin
insert BOM select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
end
update BOM set b = 2*@n -1 where b = 0
update BOM set b = 2*@n where a = 2*@n
select * from BOM
go--创建用户定义函数,每个子节点de父节点的信息
create function f_getChild(@ID int)
returns varchar(100)
as
begin
declare @i int
declare @oldid int
declare @ret varchar(100)
select @id = a from bom where b =@id
set @oldid = @id
declare @t table(ID VARCHAR(10),PID VARCHAR(10),Level INT)
set @i = 1
insert into @t select a,b,@i from BOM where A = @ID
while @@rowcount<>0
begin
set @i = @i + 1
insert into @t
select
a.a,a.b,@i
from
BOM a,@t b
where
a.b=b.ID and b.Level = @i-1 and a.a <> @oldid
end
select @ret=','+rtrim(id)+isnull(@ret,'')
from @t order by level
set @ret=stuff(@ret,1,1,'')
select @ret = @ret + '--' + min(id) from @t
return @ret
end
go--执行查询
declare @s varchar(100)
set @s = ''
select @s = @s +','+ ltrim(a)
from (
select a
from (
select a,isnull(dbo.f_getchild(a),'') as c
from bom) T
where a = substring(c,charindex('--',c)+2,100)) t
select @s= stuff(@s,1,1,'')
select @s
go
--输出结果
/*
n = 4----------------------------------------------------------------------------------------------------
1,2,4,8n = 5
----------------------------------------------------------------------------------------------------
1,2,4,10n = 6
----------------------------------------------------------------------------------------------------
1,10,12
*/--删除测试数据
drop function f_getChild
drop table BOM
go
create table BOM(a int,b int )go
declare @n int
set @n = 4
declare @i int
select @i = 1
while @i <=2*@n
begin
insert BOM select @i,(2*@i-1)%(2*@n-1)
set @i = @i+1
end
update BOM set b = 2*@n -1 where b = 0
update BOM set b = 2*@n where a = 2*@ngo--创建用户定义函数,每个子节点de父节点的信息create table tt(a int, b varchar(100))
go
create function f_getChild(@ID int)
returns int
as
begin
declare @i int
declare @oldid int
declare @ret varchar(100)
select @id = a from bom where b =@id
set @oldid = @id
declare @t table(ID VARCHAR(10),PID VARCHAR(10),Level INT)
set @i = 1
insert into @t select a,b,@i from BOM where A = @ID
while @@rowcount<>0
begin
set @i = @i + 1
insert into @t
select
a.a,a.b,@i
from
BOM a,@t b
where
a.b=b.ID and b.Level = @i-1 and a.a <> @oldid
end
select @ret=','+rtrim(id)+isnull(@ret,'')
from @t order by convert(int,id) desc
set @ret=stuff(@ret,1,1,'')
select @ret = min(cast(id as int)) from @t
return @ret
end
go--执行查询
declare @s varchar(100)
set @s = ''
select @s = @s +','+ ltrim(c)
from ( select distinct isnull(dbo.f_getchild(a),'') as c
from bom ) t
order by c
select @s= stuff(@s,1,1,'')
select @s
go
--输出结果
/*
n = 4----------------------------------------------------------------------------------------------------
1,2,4,8n = 5
----------------------------------------------------------------------------------------------------
1,2,4,10n = 6
----------------------------------------------------------------------------------------------------
1,2,12
*/--删除测试数据
drop function f_getChild
drop table BOM,tt
go
declare @n int
set @n = 5
declare @i int
select @i = 1
while @i <=@n
begin
insert @t select @i,2*@i-1
set @i = @i+1
end
insert @t select a+@n,b+1 from @t;WITH CTE (rootnode, childnode)
AS
(
select a,b
from @t where a<=@n
union all
SELECT rootnode,b
FROM @t t inner join cte on t.a=cte.childnode
where rootnode<>childnode
)
select * from cte
order by rootnode,case when rootnode=childnode then 0 else 1 end;
/*
rootnode childnode
----------- -----------
1 1
2 2
2 3
2 5
2 9
2 8
2 6
3 3
3 9
3 8
3 6
3 2
3 5
4 4
4 7
5 5
5 9
5 8
5 6
5 2
5 3(21 row(s) affected)
*/--接下来该怎么做楼主一定没问题
a b
----------- -----------
1 1
2 3
3 5
4 7
5 9
6 11
7 2
8 4
9 6
10 8
11 10
12 12 第1条记录 b=1 查找a=1的记录 还是第1条记录 构成一个环,输出
id c
1 1
第2条记录 b=2 查找a=2的记录,第3条a=3 b=5
查找a=5 的记录,第5条a=5 b=9
查找a=9 的记录,第9条a=9 b=6
...
查找a=7 的记录,第7条a=7 b=2
又回到了2 加上前面的输出
id c
1 1
2 2,3,5,9,6,11,10,8,4,7
.....
----------------------------------------第二条记录,明明b=3什么说b=2?
create function fn_分类函数(
@n int,
@x int)
returns int
as
begin
declare @t table (a int)
insert @t values(@x)
declare @i int
set @i=case when @x % 2 =0 then @n+@x/2 else (@x+1)/2 end
while @i<>@x
begin
insert @t values(@i)
set @i=case when @i% 2 =0 then @n+@i/2 else (@i+1)/2 end
end
return (select min(a) from @t)
end
go--目的函数
create function fn_目的函数(
@n int)
returns varchar(2000)
as
begin
declare @r varchar(2000)
set @r=''
declare @t table (a int)
declare @i int
set @i = 1
while @i <=2*@n
begin
insert @t values( @i)
set @i = @i+1
end
select @r=@r+','+cast(x as varchar) from (
select distinct x=dbo.fn_分类函数(@n,a) from @t
) as t
return stuff(@r,1,1,'')
end--测试
select dbo.fn_目的函数(4)
--
1,2,4,8select dbo.fn_目的函数(5)
--
1,2,4,10select dbo.fn_目的函数(6)
--
1,2,12select dbo.fn_目的函数(50)
--
1,2,4,6,10,12,16,34,100select dbo.fn_目的函数(100)
--
1,2,4,200--更大的数据需要优化算法
create table #(a int, b int)
create table #r(a int)
declare @n int
set @n=10000
insert into #t select top (@n) null from sys.sysobjects a,sys.sysobjects b,sys.sysobjects c,sys.sysobjects d
insert into # select a,2*a-1 b from #t
insert into # select a+@n,2*a from #declare @i int
select @i=(select top 1 a from #)
while @@rowcount>0
begin
insert into #r select @i;
WITH CTE (rootnode, childnode)
AS
(
select a,b
from # where a=@i
union all
SELECT rootnode,b
FROM # t inner join cte on t.a=cte.childnode
where rootnode<>childnode
)
delete t from # t inner join cte on t.a=cte.childnode
OPTION (MAXRECURSION 0); select top 1 @i=a from #
end
declare @s varchar(max)
set @s=''
select @s=@s+','+rtrim(a) from #r
select @s=rtrim(@n)+': '+stuff(@s,1,1,'')
print @sdrop table #r,#,#t/*
10000: 1,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,54,56,58,62,64,68,70,72,76,78,80,82,84,86,88,90,92,94,96,98,102,104,106,108,110,112,116,118,120,122,124,126,130,132,134,136,140,142,144,146,148,152,156,160,162,164,166,168,170,172,180,182,184,190,192,194,200,202,208,210,212,214,218,222,228,230,232,240,242,244,246,248,254,260,262,266,276,280,282,284,286,290,292,300,302,304,306,328,336,342,346,350,352,356,360,368,370,374,376,386,388,390,398,404,406,408,410,416,426,430,432,436,442,454,464,466,468,476,490,492,494,498,502,510,516,522,528,534,536,540,542,544,560,564,572,574,584,594,596,608,654,656,672,680,682,690,696,728,742,760,764,796,816,826,878,904,906,1054,1094,1108,1112,1156,1206,1360,1376,1464,1630,1690,1780,1946,2858,3582,8572,20000
*/
在sql中的算法我继续想。头痛...
--分类过程
create proc pr_分类过程
@N int,
@i int,
@tabnum int output
as
set nocount on
declare @TabName varchar(100)
set @TabName='##t'+Cast(@tabnum as nvarchar)set @tabnum=@tabnum+1declare @sql nvarchar(4000)
declare @r int
declare @ic varchar(20)
declare @nc varchar(20)
set @ic=Cast(@i as varchar)
set @nc=Cast(@n as varchar)
set @sql=N'Create table '+@TabName+' (a int)
declare @x int
declare @n int
set @x='+@ic+'
set @n='+@nc+'
insert '+@TabName+' values(@x)
declare @i int
set @i=case when @x % 2 =0 then @n+@x/2 else (@x+1)/2 end
while @i<>@x
begin
insert '+@TabName+' values(@i)
set @i=case when @i% 2 =0 then @n+@i/2 else (@i+1)/2 end
end
select @r=min(a) from '+@TabNameexec sp_executesql @sql,N'@r int output',@r output
return @r
go
--目的过程
alter proc pr_目的过程
@n int
as
set nocount on
declare @tabnum int
set @tabnum=1declare @i int
set @i=1declare @r varchar(2000)
set @r=''declare @j int
declare @sql Nvarchar(2000)
declare @b bit
declare @ri intwhile @i<=2*@n
begin
LabBeg:
set @j=1
while @j<@tabnum
begin
set @sql=N'if exists (select 1 from ##t'+cast(@j as nvarchar)+' where a='+cast(@i as nvarchar)+') select @e=1 else select @e=0'
exec sp_executesql @sql,N'@e bit output',@b output
if @b=1 --Next
begin
set @i=@i+1
goto LabBeg
end
set @j=@j+1
end
exec @ri=pr_分类过程 @N,@i,@tabnum output
set @r=@r+','+cast(@ri as varchar)
set @i=@i+1
endset @r=stuff(@r,1,1,'')
select @r as Resultset @i=1
while @i<@tabnum
begin
set @sql=N'drop table ##t'+Cast(@i as nvarchar)
exec(@sql)
set @i=@i+1
endgo
exec pr_目的过程 4
--
1,2,4,8exec pr_目的过程 5
--
1,2,4,10exec pr_目的过程 6
--
1,2,12exec pr_目的过程 50
--
1,2,4,6,10,12,16,34,100 --2秒exec pr_目的过程 100
--
1,2,4,200 -- 3秒
exec pr_目的过程 1000
--
1,2,4,6,8,10,16,2000 -- 1分09秒--更大数据不敢试了
create function f_geth(@n int)
returns varchar(8000)
as
begin
declare @t table(a int)
declare @s varchar(8000)
declare @i int,@id int,@c int
set @s = ''
set @i = 2
set @c = 2*@n -1
while @i <=@c
begin
if not exists(select 1 from @t where a= @i)
begin
set @s = @s +','+rtrim(@i/2)
insert @t select @i
set @id = (2*@i-1)%@c
if @id = 0 set @id = @c
while @i <> @id
begin
insert @t select @id
set @id = (2*@id-1)%@c
if @id = 0 set @id = @c
end
end
set @i = @i +1
end
return stuff(@s,1,1,'')
end
GO
执行
select top 10 identity(int,1000,1) id,convert(varchar(8000),'') c into # from dbo.syscolumns
update # set c = dbo.f_geth(id)
select * from #
drop table #
在我的破本本上(512m,p4 1.1g)花了11S
结果如下:
/*
id c
----------- -----------------------------------------------------------------------------------------------------------------------------------------------
1000 1,2,3,4,5,8
1001 1,2,3,4,8,12,15,16,35,44,58,73,218,334
1002 1,2,3,4,5,9,18
1003 1,2,3,4,5,6,7,8,9,10,201
1004 1,2,3,5,7,8,10,12,14,15,20,23,29,35,41,44,59,86,112,335
1005 1,2,3,4,6,11,18,21,25,39,62,74,144,431
1006 1,2,3,4,7
1007 1,2,3,4,5,6,7,9,10,11,12,13,14,16,17,19,20,21,25,28,29,31,35,37,41,43,54,55,57,60,62,75,92,104,115,153,336
1008 1,2,3,4,5,6,7,8,10,12,13,15,16,18,19,20,21,22,24,25,27,28,29,30,31,33,35,38,39,42,46,47,52,55,59,72,78,86,90,98,109,150,163,171,202,228,358,488
1009 1,2,3,5,7,9
*/