难道就没有可以解决算法!没有分该问题为靠前发了5次了
列1 列2 列3 列4
p i pi
b ao bao
l an lan
l i li
p an pan
p ao pao
b i bi
l an lan
b an ban
------------加几个数据帮助理解
zh ai zhai
b ing bing
p en pen
.....其它的数据
--------这个是数据库实际存在的,数据有1-2W数据组合,例要求列1 P出现3次,b出现3次,l出现3次,列2 --i出现3次,ao 出现2次,an 出现4次这样的条件来取数据。是在这些1-2W的数据中 随机符合我这个条件,条件是在变的,例要求 列1(声母)w出现3次,sh出现1次,d出现5次,列2(韵母) --an出现5次,ao 出现2次,ang 出现2次这样的条件来取数据,也就是说 在去得数据中列1与列2要符合我的 要求 。
问题点数:20、回复次数:61Top
1 楼rivery(river)回复于 2005-08-08 18:38:48 得分 0
问一下搂住:
例要求列1 P出现3次,b出现3次,l出现3次,列2 --i出现3次,ao 出现2次,an 出现4次这样的条件来取数据。
是在原有的数据中找到满足条件的记录还是把列1满足条件的记录和列2满足条件的记录组合到一起生成一个新的结果集?
Top
2 楼herr()回复于 2005-08-08 21:31:14 得分 0
是在原有的数据中找到满足条件的记录。
就是取的结果集中,列1和列2各列统计出满足我的条件就可以。这个条件要求可以自己定义,就是说 要出现列1(声母)、 列2(韵母)具体内容及内容数量可以根据需要来定义。
不知道我说明白了。辛苦你了!
=============
另附带说明列1是声母; 列2是韵母;列3是拼音;列4是词;Top
3 楼jimnet(jim)回复于 2005-08-09 04:56:00 得分 0
不懂Top
4 楼zhhlong(海水深蓝)回复于 2005-08-09 09:27:51 得分 0
不知所云^^^^^^^^^^^Top
5 楼coolingpipe(冷箫轻笛)回复于 2005-08-09 11:58:37 得分 0
确实没有什么算法可言
楼主倒不如写下你到底想实现什么功能
大家一起想办法
这个问题是没有什么算法的!Top
6 楼rivery(river)回复于 2005-08-09 16:18:37 得分 8
/*
处理思想:由外部条件组合成一个结果集,与原结果集联合查询。
说明:外部条件列1和列2条件的行数应该相同。并返回这个行数的结果集。
sql中没有现成的关于一个字符串的全部排列组合的函数,所以由外部程序处理传入
(我试了一下,不是马上能在sql中解决这个算法的,幸好外部程序的算法比较多,可以传入)
部分变量的定义的长度需要统一和修改。
实际也不知道这个能否满足搂住的要求。
你可以在你的数据上试试,前提是你有的外部程序有个能得出某个字符串的全部排列组合的算法。
*/
--辅助函数:将字符串变为表
CREATE FUNCTION dbo.fnt_SplitString
(
@string varchar(8000), --以分隔符为结尾。
@split_flag char(1)
)
RETURNS @tbl table
( item_id int identity(1,1),
item varchar(100)
)
as
begin
if len(isnull(@split_flag,''))=0
select @split_flag=@split_flag
if len(isnull(@string,''))=0
select @string='0'+@split_flag
if right(@string,1)<>@split_flag
select @string=@string+@split_flag
declare @var_value varchar(100) --分隔出的项值
declare @str_len integer --字符串长度
declare @str_pos integer --‘,’在字符串中的起始位置
select @str_len=len(@string)
select @str_pos=charindex(@split_flag,@string)
while @str_pos >0
begin
select @var_value=substring(@string,1,@str_pos -1)
if @var_value<>''
insert into @tbl(item) values(@var_value)
select @string=substring(@string,@str_pos+1,@str_len - @str_pos)
select @str_len=len(@string)
select @str_pos=charindex(@split_flag,@string)
end
return
end
go
--主表数据
create table #t (col1 varchar(10),col2 varchar(10),col3 varchar(50))
insert into #t
select 'p','i','pi'
union all select 'b','ao','bao'
union all select 'l','an','lan'
union all select 'l','i','li'
union all select 'p','an','pan'
union all select 'p','ao','pao'
union all select 'b','i','bi'
union all select 'l','an','lan'
union all select 'b','an','ban'
drop procedure getresult
create procedure getresult(@col1_condition varchar(200),--列1的条件,使用值,数目;....格式传递
@col2_condition varchar(200),--列2的条件,使用值,数目;....格式传递
@pstr varchar(8000)) --列2的全部排列组合,如条件:列2 a出现2次,c出现1次,则应该是a,a,c字符串的所有排列组合。
as
begin
declare @sqlstr varchar(1000)
select @sqlstr=''
select @sqlstr=@sqlstr+replicate('union all select '''+left(item,charindex('_',item)-1)+''',''0'' ',convert(int,right(item,len(item)-charindex('_',item))))
from dbo.fnt_splitstring(@col1_condition,',')
select @sqlstr='insert into #condition(col1value,flag) '+stuff(@sqlstr,1,10,'')
--辅助表1,获得每笔内容。如P出现两次,则为两条记录。
--这里是:列一:p 出现两次,b出现一次;l 出现一次;列二:i出现1次,ao出现1次,an出现两次。
create table #condition(id int identity(1,1),col1value varchar(10),flag char(1))
exec(@sqlstr)
select @sqlstr=''
select @sqlstr=@sqlstr+replicate('union all select '''+left(item,charindex('_',item)-1)+''',''1'' ',convert(int,right(item,len(item)-charindex('_',item))))
from dbo.fnt_splitstring(@col2_condition,',')
select @sqlstr='insert into #condition(col1value,flag) '+stuff(@sqlstr,1,10,'')
exec(@sqlstr)
/*
select 'p','0'
union all select 'p','0'
union all select 'b','0'
union all select 'l','0'
union all select 'i','1'
union all select 'ao','1'
union all select 'an','1'
union all select 'an','1'
*/
--外部实现的列2要出现的字母的排列组合。
--declare @pstr varchar(8000)
-------外部排列组合的程序比较多,但是我这里也没有现成的,所以手工列出来几个,以做测试。如谁有sql中的字符串排列组合的算法,可以提供一下。
--select @pstr='i,ao,an,an;i,an,ao,an;i,an,an,ao;ao,i,an,an;ao,an,i,an;ao,an,an,i;an,ao,i,an;an,ao,an,i;an,an,i,ao;an,an,ao,i;'
--辅助表2记录所有的排列组合
create table #p(id int identity(1,1),sortstr varchar(100))
insert into #p(sortstr)
select item from dbo.fnt_splitstring(@pstr,';')
--辅助表3将某个排列组合的字符串序列化为行数据。
create table #s(id int identity(1,1),colvalue varchar(20))
--循环找符合的记录
declare @outrowcount int,@i int,@allcount int,@tempcount int
select @outrowcount=count(1) from #condition where flag='0' --要输出的总行数
select @allcount=count(1) from #p
select @i=1
while @i<=@allcount
begin
--获取排序的字符串
declare @str varchar(50)
select @str=sortstr from #p where id=@i
truncate table #s
--转化为表
insert into #s(colvalue)
select item from dbo.fnt_splitstring(@str,',')
--获得结果的行数
select @tempcount=count(1)
from #t a,
(select id,col1value from #condition where flag='0') b,
(select id,colvalue from #s) c
where a.col1=b.col1value and a.col2=c.colvalue and b.id=c.id
if @tempcount=@outrowcount
break
select @i=@i+1
end
if @tempcount=@outrowcount
select a.*
from #t a,
(select id,col1value from #condition where flag='0') b,
(select id,colvalue from #s) c
where a.col1=b.col1value and a.col2=c.colvalue and b.id=c.id
else
print 'no'
drop table #condition
drop table #p
drop table #s
end
--调用测试:
declare @1 varchar(200),@2 varchar(200),@3 varchar(8000)
select @1='p_2,b_1,l_1'
select @2='i_1,ao_1,an_2'
select @3='i,ao,an,an;i,an,ao,an;i,an,an,ao;ao,i,an,an;ao,an,i,an;ao,an,an,i;an,ao,i,an;an,ao,an,i;an,an,i,ao;an,an,ao,i;'
exec getresult @1,@2,@3
--结果
/*
col1 col2 col3
----------------------
l i li
p an pan
p ao pao
b an ban
*/
Top
7 楼rivery(river)回复于 2005-08-09 16:19:57 得分 0
忘记屏蔽调试时的
drop procedure getresult
了。Top
8 楼rivery(river)回复于 2005-08-09 16:26:51 得分 0
告诉你个秘诀啊你自己回复一次,你的帖子就到前面去了。
同时很多人都想帮你的。但是真的无法理解你的意思。我也不知道理解对没。
其实这里的人是最热心的,每个问题他们都想能够得到解决。
Top
9 楼yaozw_mountain(山林)回复于 2005-08-09 18:36:15 得分 0
例中条件:要求 列1(声母)w出现3次,sh出现1次,d出现5次,
列2(韵母) --an出现5次,ao 出现2次,ang 出现2次这样的条件来取数据
也就是:
列1(声母): w(3), sh(1), d(5)
列2(韵母): an(5), ao(2), ang(2)
问题是:在这个结果集中可以不可出其他值,如:列1(声母)出现x... 列2(韵母)出现e....?
问题二:列1 的声母数目、列2的韵母数目 是不是就是3个,会不会多或者少?
这个问题可以转化成:
在源集合中,组合出现的统计数T(w_an, w_ao, w_ang, sh_an, sh_ao, sh_ang, d_an, d_ao, d_ang ),
独立出现的统计数T(w, sh, d, an ,ao, ang)
如果目标集存在,不是取自 组合集, 就是取自 独立集.
分别为:
Z_w_an, Z_w_ao, Z_w_ang, Z_sh_an, Z_sh_ao, Z_sh_ang, Z_d_an, Z_d_ao, Z_d_ang
D_w, D_sh, D_d, D_an ,D_ao, D_ang
应满足等式:
Z_w_an + Z_w_ao + Z_w_ang + D_w = w(3)
Z_sh_an+ Z_sh_ao + Z_sh_ang + D_sh = sh(1)
Z_d_an + Z_d_ao + Z_d_ang + D_d = w(3)
Z_w_an + Z_sh_an+ Z_d_an + D_an = an(5)
Z_w_ao + Z_sh_ao + Z_d_ao + D_ao = ao(2)
Z_w_ang + Z_sh_ang +Z_d_ang + D_ang = ang(2)
和不等式:
Z_w_an < T_w_an
Z_w_ao < T_w_ao
Z_w_ang < T_w_ang
Z_sh_an < T_sh_an
Z_sh_ao < T_sh_ao
Z_sh_ang< T_sh_ang
Z_d_an < T_d_an
Z_d_ao < T_d_ao
Z_d_ang < T_d_ang
D_w < T_w
D_sh < T_sh
D_d < T_d
D_an < T_an
D_ao < T_ao
D_ang < T_ang
在简化公式后在求数。这个例子中组合统计数应为0,1Top
10 楼filebat(Mark)回复于 2005-08-09 19:13:06 得分 0
rivery,你真有耐心啊。
你贴的代码,滚了五下滚轮才滚完。
楼主,不给他全分,就不厚道哦。Top
11 楼rivery(river)回复于 2005-08-09 21:16:48 得分 0
^_^,关键搂住似乎对这里有点灰心。
而我又感觉自己理解了有点他的意思(也不知道对不),
所以就耗费了半天的时间弄了一下,倒是排列组合难住了。没想到好的方法。
楼上有空帮忙写个sql的某个字符串的排列组合的算法。
Top
12 楼herr()回复于 2005-08-09 22:58:18 得分 0
rivery(river) 辛苦了,我TESTTop
13 楼yaozw_mountain(山林)回复于 2005-08-11 17:45:55 得分 2
-- 感谢 rivery 给于的灵感,用以下方法返回所有的组合,大家互相探讨
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[uf_BitNumber]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[uf_BitNumber]
GO
create function uf_BitNumber (@in bigint)
returns int as
begin
declare @i int, @n bigint
set @i = 0
set @n = @in
while @n >0
begin
if @n % 2 >0
begin
set @i = @i +1
end
set @n = @n /2 -- FLOOR
end
return @i
end
GO
--主表数据
declare @tsrc table (id int IDENTITY(0,1) PRIMARY KEY, c1 varchar(10),c2 varchar(10),c3 varchar(50))
insert into @tsrc (c1,c2,c3)
select 'p','i' ,'pi'
union all select 'b','ao','bao'
union all select 'l','an','lan'
union all select 'l','i' ,'li'
union all select 'p','an','pan'
union all select 'p','ao','pao'
union all select 'b','i' ,'bi'
union all select 'l','an','lan'
union all select 'b','an','ban'
declare @c1str as varchar(400), @c2str as varchar(400), @sqlstr as varchar(400)
set @c1str ='p_2,b_1,l_1'
set @c2str ='i_1,ao_1,an_2'
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tc1') and type='U' ) drop table #tc1
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tc2') and type='U' ) drop table #tc2
create table #tc1 ( i varchar(40), n int, h bigint)
create table #tc2 ( i varchar(40), n int, h bigint)
declare @tgrp table (id int IDENTITY(0,1) PRIMARY KEY,id0 int, c1 varchar(10),c2 varchar(10)/*, mcnt int*/, h bigint)
declare @tout table (id int IDENTITY(0,1) PRIMARY KEY,id0 int, c1 varchar(10),c2 varchar(10)/*, mcnt int*/, h bigint)
set @sqlstr = 'select ''' +replace(replace(@c1str,',',' union all select ''') ,'_',''',')
insert into #tc1(i,n) exec ( @sqlstr )
set @sqlstr = 'select ''' +replace(replace(@c2str,',',' union all select ''') ,'_',''',')
insert into #tc2(i,n) exec ( @sqlstr )
insert into @tgrp (c1, c2, id0 )
select c1,c2, id from @tsrc,(
select a.i i1, b.i i2 from #tc1 a, #tc2 b
) x
where x.i1 = c1 and x.i2 = c2
update @tgrp set h=power(2,id)
update #tc1 set h=x.h from (
select c1, sum(h) h from @tgrp group by c1
) x, #tc1 a
where x.c1 = a.i
update #tc2 set h=x.h from (
select c2, sum(h) h from @tgrp group by c2
) x, #tc2 a
where x.c2 = a.i
declare @max as int, @max2 as int, @i as int
select @max= count(*) from @tgrp
set @max2 = power(2, @max )-1
while @max2 >0
begin
if not exists( select * from #tc1 where dbo.uf_BitNumber( h & @max2) <> n )
and not exists( select * from #tc2 where dbo.uf_BitNumber( h & @max2) <> n )
begin
insert into @tout(c1,c2,h, id0 )
select c1,c2, @max2,id0 from @tgrp where @max2 & h >0
end
set @max2 = @max2 -1
end
select count(DISTINCT h) from @tout
select * from @tout order by h, id0
drop table #tc1
drop table #tc2
/*
这个方法使用bit 代表各种组合,返回所有的可能的组合.
限制-- (声母(这里是3) * 韵母(这里是3)) (即@tgrp记录数) < 62(整数位数)
如果需要突破这限制,可以用varchar/ varbinary/ 多个bigint 代替 bigint ,并替换以下方法:
Power(移位), Sum(|或,聚合函数) , &(与), uf_BitNumber(1的计数), @max2
如(varchar(4000)):
set @max2a = REPLICATE('1',@max)
set @max2b = REPLICATE('0',@max)
set @max2 = @max2a
移位: STUFF( @max2b, id,1,'1')
或,聚合: bintochar(sum(chartobin()): varchar bintochar(dec(30)), dec(30) chartobin(varchar) ........
与: charAND(varchar,varchar)......
1的计数: len( REPLACE(charAND( h, @max2), '0','')
*/
/*
结果:(7组)
id id0 c1 c2 h
_______________________________________
24 0 p i 75
26 1 b ao 75
27 2 l an 75
25 4 p an 75
23 2 l an 86
20 4 p an 86
21 5 p ao 86
22 6 b i 86
16 0 p i 101
19 2 l an 101
17 5 p ao 101
18 8 b an 101
15 3 l i 166
12 4 p an 166
13 5 p ao 166
14 8 b an 166
8 0 p i 267
10 1 b ao 267
9 4 p an 267
11 7 l an 267
4 4 p an 278
5 5 p ao 278
6 6 b i 278
7 7 l an 278
0 0 p i 293
1 5 p ao 293
3 7 l an 293
2 8 b an 293
*/Top
14 楼herr()回复于 2005-08-11 22:10:04 得分 0
rivery 超出了存储过程、函数、触发器或视图的最大嵌套层数(最大层数为 32)。Top
15 楼j9988(j9988)回复于 2005-08-11 22:43:42 得分 10
有几项你没说明白:
1.这表你应该有个主键.比如ID之类的.否则你组合出来的结果抽那一条没什么意思.
2.随机组合容易.但不存在的组合,你得事先剔除.比如: g k h 和 ian 组合就不存在.是前台去除还是后台处理?
后台处理:
sekect distinct 列1,列2,列3 into NewTable from YourTable
先产生一个可能的组合表.
3.因为以上原因,传入的条件是否有所限制??
4.你的表二万多记录,是所有汉字都存在? 还是其它什么? 表述不够细.
给出真实的表结构和内容.和你如此查询的真实目的与用处. 这样大家也好看看.
Top
16 楼herr()回复于 2005-08-11 23:18:19 得分 0
1.这表你应该有个主键.比如ID之类的.否则你组合出来的结果抽那一条没什么意思.
答:ID 主键 ,结果抽出是根据条件的提取,表的数据是这样的
id 列1 列2 列3 列4
1 p i pi
2 b ao bao
3 l an lan
4 l i li
5 p an pan
6 p ao pao
7 b i bi
8 l an lan
9 b an ban
10 zh ai zhai
11 b ing bing
12 p en pen
。。。等数据
id 列1 列2 列3 列4---》说明如下
id 主键自动ID
列1 是 声母
列2 是 韵母
列3 是 该词或者词组的拼音
列4 是 该词或者词组,即中文汉字
要求是这样,现在要出一道题目共100个字,要求含声母b,l,zh与韵母ao,ban,en提取数据(这里只说明意思列出这点声母与韵母),
但是在提取100个字中,要求含声母b出现50次,l出现20次,zh出现32次 韵母ao出现12次,ban出现38次,en出现50次。
也就是,按要求提取相应的数据来。
2.随机组合容易.但不存在的组合,你得事先剔除.比如: g k h 和 ian 组合就不存在.是前台去除还是后台处理?
答:实际上不是随机组合,因为在我选择的声母与韵母范围来提取数据,不可以组合,可以控制,有一定规律,可以在过滤掉的。后台这里出题提供条件,在前台每一人点后随机出来数据,在数据上区别是同音不同字,但是不足要求提取的数量必须提示 。
3.因为以上原因,传入的条件是否有所限制??
答:传入 是对应声母与韵母以及出现次数和总取的总字数[也就是实际声母与韵母各自的总数,例要取100个字,那么声母100与韵母100]
4.你的表二万多记录,是所有汉字都存在? 还是其它什么? 表述不够细.
答:是我们试题需要的相关字。相关看上述描述
Top
17 楼j9988(j9988)回复于 2005-08-11 23:38:00 得分 0
因为数据库随机取数,可以对横向处理,对纵向处理恐怕很难.
只有象以上回答一样先随机组合出一组可能有组合.
然后再随机从题库出找抽出结果.
所以还是随机组合.这样的后果也许你数据库中有符合要求的结果.但抽不出足额的记录.
Top
18 楼j9988(j9988)回复于 2005-08-12 00:00:30 得分 0
--b出现50次,l出现20次,zh出现32次 韵母ao出现12次,ban出现38次,en出现50次。
--1.先把声母韵母要求的记录组存入表
declare @s1 varchar(8000),@s2 varchar(8000)
select @s1=replicate('p,',50)+replicate('l,',18)+replicate('zh,',32),
@s2=replicate('ao,',32)+replicate('an,',18)+replicate('en,',50)
select @s1=left(@s1,len(@s1)-1),@s2=left(@s2,len(@s2)-1)
select @s1='select '''+replace(@s1,',',''' union all select ''')+'''',
@s2='select '''+replace(@s2,',',''' union all select ''')+''''
create table #t1(id int identity,s varchar(10))
create table #t2(s varchar(10))
insert #t1 exec(@s1)
insert #t2 exec(@s2)
--2.用order by newid()把韵母随机打乱
declare @a table(id int identity,s varchar(10))
insert @a(s) select s from #t2 order by newID()
select A.s as 声母,B,s as 韵母 from #t1 A,@a B where A.id=B.id
--@b 存随机抽出的ID
declare @b(id int)
declare @声母 varchar(10),@韵母 varchar(10)
--用游标100次循环随机抽出符合条件不重复的ID
declare c cursor for
select A.s,B,s from #t1 A,@a B where A.id=B.id
OPEN c
FETCH NEXT FROM authors_cursor
INTO @声母,@韵母
WHILE @@FETCH_STATUS = 0
begin
insert @b
select id from 源表
where 列1=@声母 and 列1=@韵母
and id not in (select id from @b)
FETCH NEXT FROM authors_cursor
INTO @声母,@韵母
end
drop table #t1,#t2
--最后跟据得到的ID从源表中取出结果.
select * from 源表 where id in (select id from 源表 )
Top
19 楼j9988(j9988)回复于 2005-08-12 00:07:52 得分 0
--别忘了关闭游标
CLOSE c
DEALLOCATE c
就当所有组合都存在.都可以找出记录.如果组合不存在,
在组合结果时要先调整.比如:
调束措失:
select 列1,列2,count(*) 存在记录数 into newTable from 源表 group by 列1,列2
这样你在传入条件时先做些判断,适当调整随机组合的声母韵母结果.
然后再随机抽取.Top
20 楼j9988(j9988)回复于 2005-08-12 01:42:14 得分 0
--错了,要改一下
WHILE @@FETCH_STATUS = 0
begin
insert @b
select top 1 id from 源表
where 列1=@声母 and 列1=@韵母
and id not in (select id from @b)
order by newid()
FETCH NEXT FROM authors_cursor
INTO @声母,@韵母
end
Top
21 楼herr()回复于 2005-08-12 09:15:18 得分 0
j9988 辛苦了 我TEST 是否可以满足Top
22 楼j9988(j9988)回复于 2005-08-12 10:10:52 得分 0
--b出现50次,l出现20次,zh出现32次 韵母ao出现12次,ban出现38次,en出现50次。
--1.先把声母韵母要求的记录组存入表
declare @s1 varchar(8000),@s2 varchar(8000)
select @s1=replicate('p,',50)+replicate('l,',18)+replicate('zh,',32),
@s2=replicate('ao,',32)+replicate('an,',18)+replicate('en,',50)
select @s1=left(@s1,len(@s1)-1),@s2=left(@s2,len(@s2)-1)
select @s1='select '''+replace(@s1,',',''' union all select ''')+'''',
@s2='select '''+replace(@s2,',',''' union all select ''')+''''
create table #t1(id int identity,s varchar(10))
create table #t2(s varchar(10))
insert #t1 exec(@s1)
insert #t2 exec(@s2)
--2.用order by newid()把韵母随机打乱
declare @a table(id int identity,s varchar(10))
insert @a(s) select s from #t2 order by newID()
select A.s as 声母,B,s as 韵母 from #t1 A,@a B where A.id=B.id
--@b 存随机抽出的ID
declare @b(id int)
declare @声母 varchar(10),@韵母 varchar(10)
--用游标100次循环随机抽出符合条件不重复的ID
declare c cursor for
select A.s,B,s from #t1 A,@a B where A.id=B.id
OPEN c
FETCH NEXT FROM authors_cursor
INTO @声母,@韵母
WHILE @@FETCH_STATUS = 0
begin
insert @b
select top 1 id from 源表
where 列1=@声母 and 列1=@韵母
and id not in (select id from @b)
order by newid()
FETCH NEXT FROM authors_cursor
INTO @声母,@韵母
end
drop table #t1,#t2
--最后跟据得到的ID从源表中取出结果.
--select * from 源表 where id in (select id from 源表 )
select * from 源表 where id in (select id from @b)---这儿改一下.Top
23 楼j9988(j9988)回复于 2005-08-12 10:12:19 得分 0
应该基本上可以符合你的要求,但缺点是:就是怕组合出的结果有些在源表中找不到.Top
24 楼yaozw_mountain(山林)回复于 2005-08-12 10:38:49 得分 0
怎么像 拼音练习
“在提取100个字中,要求含声母b出现50次,l出现20次,zh出现32次 韵母ao出现12次,ban出现38次,en出现50次”:如果只有 b,l,zh; ao,ban,en组合怎么也得不到100个汉字,是不是有其他字母,只是不计数??
j9988(j9988) 的
“--用游标100次循环随机抽出符合条件不重复的ID
declare c cursor for
select A.s,B,s from #t1 A,@a B where A.id=B.id
”
这样撞大运,成功概率不知怎样
Top
25 楼herr()回复于 2005-08-12 10:41:11 得分 0
where 列1=@声母 and 列1=@韵母 --->应该是where 列1=@声母 and 列2=@韵母 吧
Top
26 楼prcgolf(小鸟)回复于 2005-08-12 11:13:27 得分 0
upTop
27 楼j9988(j9988)回复于 2005-08-12 11:59:30 得分 0
where 列1=@声母 and 列1=@韵母 --->应该是where 列1=@声母 and 列2=@韵母 吧
是的.错了
Top
28 楼herr()回复于 2005-08-12 12:07:17 得分 0
我给你留言了,请查收Top
29 楼j9988(j9988)回复于 2005-08-12 12:08:30 得分 0
yaozw_mountain(山林) :
"“--用游标100次循环随机抽出符合条件不重复的ID
declare c cursor for
select A.s,B,s from #t1 A,@a B where A.id=B.id
这样撞大运,成功概率不知怎样
"
---你的理解可能成问题,到了这就不是"撞大运"了,这是有结果后,再从库中相同声韵中随机抽出一条.
--至于根本就不存在100条记录,那还何谈随机可言?
最重要应该是:记录分布不均,我前面已经说过了,
select 列1,列2,count(*) 存在记录数 into newTable from 源表 group by 列1,列2
组合记录时应该根据上面语句分析,再生成:
select A.s,B,s from #t1 A,@a B where A.id=B.id 结果集.
Top
30 楼j9988(j9988)回复于 2005-08-12 12:10:05 得分 0
declare @b table(id int)
Top
31 楼yaozw_mountain(山林)回复于 2005-08-12 14:05:24 得分 0
“select A.s,B,s from #t1 A,@a B where A.id=B.id
” 这个“结果”,并没有先得到源表的验证
只有满足以下条件,才有结果:
if not exists ( select * from (
select s1,s2, count(*) cnt from (
select A.s s1,B.s s2 from #t1 A,@a B where A.id=B.id
) group by s1, s2
) r
where cnt> (
select count(*) from 源表 b where b.列1 = r.s1 and b.列2= r.s2
)
-- ok
再问搂主!!!!!!!
“在提取100个字中,要求含声母b出现50次,l出现20次,zh出现32次 韵母ao出现12次,ban出现38次,en出现50次”:如果只有 b,l,zh; ao,ban,en组合怎么也得不到100个汉字,是不是有其他字母,只是不计数??
还是不是因为包含多音字。
还有:
声母/韵母个数(不包含重复值)最多会有多少?
Top
32 楼yaozw_mountain(山林)回复于 2005-08-12 14:14:51 得分 0
如果随机排序得到结果集的概率较大,就可以循环随机排序。否则需要较长时间了Top
33 楼rivery(river)回复于 2005-08-12 14:17:29 得分 0
热闹了,高人也就出现了。
齐心协力,问题也会解决了。
期待着搂住满怀欢喜的那个帖子:问题都解决了!最终的解决代码如下。。。。。。Top
34 楼yaozw_mountain(山林)回复于 2005-08-12 14:26:21 得分 0
declare @t table(s1 varchar(40), s2 varchar(40), cnt int)
insert into @t(s1,s2,cnt)
select 列1,列2,count(*) from 源表 group by 列1,列2
if not exists ( select * from (
select s1,s2, count(*) cnt from (
select A.s s1,B.s s2 from #t1 A,@a B where A.id=B.id
) group by s1, s2
) r
where cnt> isnull( (
select cnt from @t b where b.s1 = r.s1 and b.s2= r.s2
), 0)
)
-- ok
Top
35 楼herr()回复于 2005-08-12 14:31:19 得分 0
yaozw_mountain(山林)
--“在提取100个字中,要求含声母b出现50次,l出现20次,zh出现32次 韵母ao出现12次,ban出现38次,en出现50次”:如果只有 b,l,zh; ao,ban,en组合怎么也得不到100个汉字,是不是有其他字母,只是不计数??
\\般来说在老师出题目的时候他回作细小的估计,基本是可以组合出个数,以上是我写的例数量,在这几个里是不可能.
--还是不是因为包含多音字。
\\是的
Top
36 楼yaozw_mountain(山林)回复于 2005-08-12 14:35:08 得分 0
declare @t table(s1 varchar(40), s2 varchar(40), cnt int)
insert into @t(s1,s2,cnt)
select s1,s2, (
select count(*) from 源表 b where b.列1 = r.s1 and b.列2= r.s2
) cnt from (
select distinct A.s s1,B.s s2 from #t1 A,#t2 B where A.id=B.id
)
if not exists ( select * from (
select s1,s2, count(*) cnt from (
select A.s s1,B.s s2 from #t1 A,@a B where A.id=B.id
) group by s1, s2
) r , @t b
where b.s1 = r.s1 and b.s2= r.s2 and r.cnt> b.cnt
)
-- okTop
37 楼j9988(j9988)回复于 2005-08-12 21:05:12 得分 0
惭愧! 山林说的是对的.确实存在这种情况. 对不起!!!!
会有解决方法.正思考中....可惜现在喝多了.Top
38 楼j9988(j9988)回复于 2005-08-13 11:02:25 得分 0
declare @s1 varchar(8000),@s2 varchar(8000)
declare @num int
set @num=50 --总记录数
select @s1=replicate('d,',15)+replicate('f,',13)+replicate('b,',12),
@s2=replicate('an,',12)+replicate('ang,',13)+replicate('ao,',15)
select @s1=left(@s1,len(@s1)-1),@s2=left(@s2,len(@s2)-1)
select @s1='select '''+replace(@s1,',',''' union all select ''')+''''
,@s2='select '''+replace(@s2,',',''' union all select ''')+''''
create table #t1(id int identity,s1 varchar(10),s2 varchar(10))
create table #t2(id int identity,s varchar(10))
insert #t1(s1) exec(@s1)
insert #t2(s) exec(@s2)
select voice0 as sm,rhyme0 as ym,count(*) as num into #t_num from T_SyllableData
group by voice0,rhyme0
order by voice0,rhyme0
declare @id1 int,@s varchar(10),@id2 int
set @id1=1
while @id1<=@num
begin
update A set @s=s2=(select top 1 s from #t2 B where (select num from #t_num where sm=A.s1 and ym=B.s)-(select count(*) from #t1 where s2=B.s)>0 order by newid())
from #t1 A where id=@id1
select @id2=(select top 1 id from #t2 where s=@s)
delete #t2 where id=@id2
select @id1=@id1+1,@id2=0,@s=''
end
set @id1=1
declare @b table(id int)
while @id1<=@num
begin
insert @b
select top 1 SDid from T_SyllableData A,#t1 B
where voice0=B.s1
and rhyme0=B.s2
and B.id=@id1
and SDid not in (select id from @b)
order by newid()
set @id1=@id1+1
end
select * from T_SyllableData where SDid in (select id from @b)
order by voice0,rhyme0
--select * from #t2
drop table #t1,#t_num,#t2Top
39 楼j9988(j9988)回复于 2005-08-13 11:02:58 得分 0
完成了!Top
40 楼j9988(j9988)回复于 2005-08-13 11:04:08 得分 0
所有组合绝对可以在源表中找到.Top
41 楼j9988(j9988)回复于 2005-08-13 11:09:45 得分 0
--与前面不同之处做一些注释补充
set @num=40 --总记录数
--从源表中统计出各种组合的记录数.
select voice0 as sm,rhyme0 as ym,count(*) as num into #t_num from T_SyllableData
group by voice0,rhyme0
order by voice0,rhyme0
--往声母表中填韵母,并且填一删一个,确保韵母总数正确,
--且同时判断这种填入组合是否在源表中存在,且总抽取数不超过源表中的组合数.
declare @id1 int,@s varchar(10),@id2 int
set @id1=1
while @id1<=@num
begin
update A set @s=s2=(select top 1 s from #t2 B where (select num from #t_num where sm=A.s1 and ym=B.s)-(select count(*) from #t1 where s2=B.s)>0 order by newid())
from #t1 A where id=@id1
select @id2=(select top 1 id from #t2 where s=@s)
delete #t2 where id=@id2
select @id1=@id1+1,@id2=0,@s=''
end
Top
42 楼herr()回复于 2005-08-14 14:04:22 得分 0
j9988(j9988) 发信息给你,结构变动.Top
43 楼prcgolf(小鸟)回复于 2005-08-14 17:45:07 得分 0
upTop
44 楼j9988(j9988)回复于 2005-08-14 23:18:37 得分 0
create table T_SyllableFrom (
Sfid numeric identity,--key -----可要可不要!
SDid numeric null,--key
wstid int null,--类型ID
idorder int null,--词组的前后序号
voice varchar(50) null,--声母
rhyme varchar(50) null,--韵母日常书写
rhymefact varchar(50) null,--标准韵母
expression varchar(50) null--声调 1,2 3,4
)
--在sdid,idorder上建联合主键,这种表没有索引和主键是不可思异的
create clustered index CluInd_Syl on T_SyllableFrom(sdid,idorder)
--从原表插入数据
insert INTO T_SyllableFrom
SELECT SDid,wstid,idorder=1,voice0 as voice ,rhyme0 as rhyme,rhyme00 as rhymefact,expression0 as expression from T_SyllableData
where voice0 is not null
union all
SELECT SDid,wstid,idorder=2,voice1 as voice ,rhyme1 as rhyme,rhyme01 as rhymefact,expression1 as expression from T_SyllableData
where voice1 is not null
union all
SELECT SDid,wstid,idorder=3,voice1 as voice ,rhyme2 as rhyme,rhyme02 as rhymefact,expression2 as expression from T_SyllableData
where voice2 is not null
union all
SELECT SDid,wstid,idorder=4,voice1 as voice ,rhyme3 as rhyme,rhyme03 as rhymefact,expression3 as expression from T_SyllableData
where voice3 is not null
这样表修改后,可扩展性大大增强.你原来的表只能固定最多四字词.这样一改随意性就强了.
原表如果碰到"一夫挡关,万夫莫开" 或 "不管三七二十一" 就得改表结构,这是表设计中最忌讳的.
Top
45 楼j9988(j9988)回复于 2005-08-14 23:22:03 得分 0
从表按要求建立好后,执行以下过程,出100道题,在我的S1.7 的PC上不到2秒.
declare @s1 varchar(8000),@s2 varchar(8000)
declare @num int
set @num=100 --总记录数
select @s1=replicate('d,',45)+replicate('f,',33)+replicate('b,',32),
@s2=replicate('an,',32)+replicate('ang,',33)+replicate('ao,',35)
select @s1=left(@s1,len(@s1)-1),@s2=left(@s2,len(@s2)-1)
select @s1='select '''+replace(@s1,',',''' union all select ''')+''''
,@s2='select '''+replace(@s2,',',''' union all select ''')+''''
create table #t1(id int identity,s1 varchar(10),s2 varchar(10))
create table #t2(id int identity,s varchar(10))
insert #t1(s1) exec(@s1)
insert #t2(s) exec(@s2)
select voice as sm,rhyme as ym,count(*) as num into #t_num from T_SyllableFrom
group by voice,rhyme
order by voice,rhyme
declare @id1 int,@s varchar(10),@id2 int
set @id1=1
while @id1<=@num
begin
update A set @s=s2=(select top 1 s from #t2 B where (select num from #t_num where sm=A.s1 and ym=B.s)-(select count(*) from #t1 where s2=B.s)>0 order by newid())
from #t1 A where id=@id1
select @id2=(select top 1 id from #t2 where s=@s)
delete #t2 where id=@id2
select @id1=@id1+1,@id2=0,@s=''
end
set @id1=1
declare @b table(id int,orderid int)
while @id1<=@num
begin
insert @b
select top 1 SDid,idorder from T_SyllableFrom A,#t1 B
where voice=B.s1
and rhyme=B.s2
and B.id=@id1
and SDid not in (select id from @b)
order by newid()
set @id1=@id1+1
end
drop table #t1,#t_num,#t2
select A.* from T_SyllableFrom A,@b B where A.sdid=B.id and A.idorder=B.orderid
order by sdid,idorder
Top
46 楼j9988(j9988)回复于 2005-08-14 23:30:47 得分 0
喔,while这一段没改好,应该这样:
while @id1<=@num
begin
insert @b
select top 1 SDid,idorder from T_SyllableFrom A,#t1 B
where voice=B.s1
and rhyme=B.s2
and B.id=@id1
and not exists (select 1 from @b where id=A.sdid and orderid=A.idorder)
order by newid()
set @id1=@id1+1
end
把这一段改到上面的过程去,就完全正确了Top
47 楼prcgolf(小鸟)回复于 2005-08-15 09:06:53 得分 0
upTop
48 楼herr()回复于 2005-08-15 09:21:00 得分 0
多音节,如何来解决Top
49 楼yaozw_mountain(山林)回复于 2005-08-16 18:34:07 得分 0
j9988注意不错!
这是用逐步推演的方式,以但是仍然存在无解的风险:
上面的语句中:
update A set @s=s2=(select top 1 s from #t2 B where (select num from #t_num where sm=A.s1 and ym=B.s)-(select count(*) from #t1 where s2=B.s)>0 order by newid())
from #t1 A where id=@id1
逐步组合掉韵母,很有可能在子查询:
select top 1 s from #t2 B where (select num from #t_num where sm=A.s1 and ym=B.s)-(select count(*) from #t1 where s2=B.s)>0
在一部分韵母被组合掉后,出现空集合的可能,
特别是如果后边声母与韵母组合数本身很少,前面的声母可能组合完他们的声母,
到后来就很可能完成不了
显然无解的风险比随机的方式会小多了
Top
50 楼yaozw_mountain(山林)回复于 2005-08-16 18:39:10 得分 0
sorry! 错字太多
如果后边声母与韵母组合数本身很少,前面的声母可能组合完他们的韵母Top
51 楼j9988(j9988)回复于 2005-08-17 00:08:21 得分 0
yaozw_mountain(山林) 所说的出现过.仅是在类似于P 50 L 32 B 18 这类情况下.
而实际情况是:出100题是:p(5) l(3) b(7).......... 不会是仅两三个字母.
分别各有十几二十个声母.
目前herr给的实际表中仅4000多记录.P 50 L 32 B 18 这类情况,十次仅三五次得到99,98,97条记录.其它全是100条记录
出100题是:p(5) l(3) b(7).......... 可以做到100题出全.
所以过程还是可靠的.
如果正式运行,楼主说有二万多记录.那更是运行没问题.
仅是提供一个方法而已.细节还是要自已去做.
Top
52 楼yaozw_mountain(山林)回复于 2005-08-17 09:00:50 得分 0
--************************* << No. 3 >>*****************************************************
-- << 该算法的思想是:在源中得到声母-韵母对的最大数,在这个范围内取数组合中满足条件即为组合解 >>
--主表数据
declare @tsrc table (id int IDENTITY(0,1) PRIMARY KEY, c1 varchar(10),c2 varchar(10),c3 varchar(50))
insert into @tsrc (c1,c2,c3)
select 'p','i' ,'pi'
union all select 'b','ao','bao'
union all select 'l','an','lan'
union all select 'l','i' ,'li'
union all select 'p','an','pan'
union all select 'p','ao','pao'
union all select 'b','i' ,'bi'
union all select 'l','an','lan'
union all select 'b','an','ban'
declare @c1str as varchar(400), @c2str as varchar(400)
set @c1str ='p_2,b_1,l_1'
set @c2str ='i_1,ao_1,an_2'
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tc1') and type='U' ) drop table #tc1
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tc2') and type='U' ) drop table #tc2
create table #tc1 ( i varchar(40), n int )
create table #tc2 ( i varchar(40), n int )
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#g') and type='U' ) drop table #g
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tgout') and type='U' ) drop table #tgout
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tout') and type='U' ) drop table #tout
create table #g (i int IDENTITY(0,1) PRIMARY KEY, c1 varchar(10),c2 varchar(10), n int )
create table #tgout (i int IDENTITY(0,1) PRIMARY KEY, s varchar(4000) )
create table #tout (id int IDENTITY(0,1) PRIMARY KEY,id0 int, c1 varchar(10),c2 varchar(10),grp varchar(300))
CREATE INDEX index_g_c1 ON #g ( c1 )
CREATE INDEX index_g_c2 ON #g ( c2 )
CREATE INDEX index_tout_c2 ON #tout ( c1,c2 )
declare @sqlstr as varchar(8000), @m1 as int
set @sqlstr = 'select ''' +replace(replace(@c1str,',',' union all select ''') ,'_',''',') ; insert into #tc1(i,n) exec ( @sqlstr )
set @sqlstr = 'select ''' +replace(replace(@c2str,',',' union all select ''') ,'_',''',') ; insert into #tc2(i,n) exec ( @sqlstr )
select @m1 = count(*) from #tc1
if (select sum(n) from #tc1) <> ( select sum( n) from #tc2) return ---1 Error Input
insert into #g (c1, c2, n )
select c1,c2, count(*) from @tsrc,(
select a.i i1, b.i i2 from #tc1 a, #tc2 b
) x
where x.i1 = c1 and x.i2 = c2
group by c1,c2
declare @max as int, @max2 as int, @mg as int, @i as int
select @max= count(*) from #g
select @mg = max(n) + 1 from #g
if exists(select * from #tc1 x where(select isnull(sum(n),0) from #g g where x.i=g.c1)< x.n) return ---2No Result
if exists(select * from #tc2 x where(select isnull(sum(n),0) from #g g where x.i=g.c2)< x.n) return ---2No Result
-- 开始处理
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#n') and type='U' ) drop table #n
--create table #n (i int IDENTITY(0,1) PRIMARY KEY )
SET ROWCOUNT @mg
select IDENTITY(int, 0,1 ) as i
into #n
from sysobjects a, sysobjects b, sysobjects c
SET ROWCOUNT 0
/*
select a1.i+','+a2.i+','+a3.i+','+...
from (select top ?1 i from #n) a1,(select top ?2 i from #n) a2,...
where (a1.i +...)c1=??
and ............
and (a1.i +...)c2=??
and ............
*/
declare @s1 as varchar(4000), @s2 as varchar(4000), @sx1 varchar(4000), @sx2 varchar(4000), @tc_i varchar(20), @tc_n int
-- where form1
DECLARE @cursor_tc CURSOR
SET @cursor_tc = CURSOR FORWARD_ONLY READ_ONLY FOR
select i,n from #tc1
set @sx1=''
OPEN @cursor_tc
FETCH NEXT FROM @cursor_tc INTO @tc_i, @tc_n
WHILE @@FETCH_STATUS = 0
BEGIN
set @s1=''
select @s1=@s1 + '+a'+cast(i as varchar)+'.i' from #g g where g.c1 = @tc_i
set @sx1=@sx1 + ' and '+STUFF(@s1,1,1,'') +'=' + cast(@tc_n as varchar)
FETCH NEXT FROM @cursor_tc INTO @tc_i, @tc_n
END
CLOSE @cursor_tc
set @sx1= STUFF(@sx1,2,3,'where')
SET @cursor_tc = CURSOR FORWARD_ONLY READ_ONLY FOR
select i,n from #tc2
set @sx2=''
OPEN @cursor_tc
FETCH NEXT FROM @cursor_tc INTO @tc_i, @tc_n
WHILE @@FETCH_STATUS = 0
BEGIN
set @s1=''
select @s1=@s1 + '+a'+cast(i as varchar)+'.i' from #g g where g.c2 = @tc_i
set @sx2=@sx2 + ' and '+STUFF(@s1,1,1,'') +'=' + cast(@tc_n as varchar)
FETCH NEXT FROM @cursor_tc INTO @tc_i, @tc_n
END
CLOSE @cursor_tc
DEALLOCATE @cursor_tc
-- get @sx1, @sx2 ...>> 271
set @s1=''; set @s2=''
select @s1=@s1 + '+str(a'+cast(i as varchar)+'.i,4)',
@s2=@s2 + ',(select i from #n where i<'+cast(n+1 as varchar)+')a'+cast(i as varchar)
from #g order by i
set @s1=STUFF(@s1,1,1,''); set @s2=STUFF(@s2,1,1,'')
set @sqlstr = 'select '+@s1 +' from ' -- + @s2
/* -- where form2
set @sx1 = ' where not exists(select * from #tc1 x where(select isnull(sum(n),0) from(select cast(substring('+@s1+',g.i*4+1,4) as int)n from #g g where x.i=g.c1)n)<>x.n)'
set @sx2 = ' and not exists(select * from #tc2 x where(select isnull(sum(n),0) from(select cast(substring('+@s1+',g.i*4+1,4) as int)n from #g g where x.i=g.c2)n)<>x.n)'
*/
/* -- where form3
set @sqlstr= 'select s from(select '+@s1 +' s from ' + @s2 +
')a where not exists(select * from #tc1 x where(select isnull(sum(n),0) from(select cast(substring(a.s,g.i*4+1,4) as int)n from #g g where x.i=g.c1)n)<>x.n)'+
' and not exists(select * from #tc2 x where(select isnull(sum(n),0) from(select cast(substring(a.s,g.i*4+1,4) as int)n from #g g where x.i=g.c2)n)<>x.n)'
*/
insert into #tgout(s)exec(@sqlstr + @s2 + @sx1 + @sx2)
select * from(
select a.i idgrp, cast(substring(a.s,g.i*4+1,4) as int)n,g.n m,c1,c2
from #g g, #tgout a)x
where n>0
order by idgrp,c1,c2
/*
得到所有解组合集(每个解分组中声母-韵母对提取n个):
idgrp n m c1 c2
解分组/提取数/源中最大数/声母-韵母对
---------------------------------------
0 1 1 b an
0 1 1 l i
0 1 1 p an
0 1 1 p ao
1 1 1 b ao
1 1 2 l an
1 1 1 p an
1 1 1 p i
2 1 1 b i
2 1 2 l an
2 1 1 p an
2 1 1 p ao
3 1 1 b an
3 1 2 l an
3 1 1 p ao
3 1 1 p i
这里已经得到所有解的组合,只需要从源中提取声母-韵母对,
可以随机方式取,也可以按照m中取n的组合得到所有解。
*/
Top
53 楼yaozw_mountain(山林)回复于 2005-08-17 09:03:44 得分 0
-- 按照m中取n的组合得到所有解
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tid0') and type='U' ) drop table #tid0
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tidx') and type='U' ) drop table #tidx
if exists( select * from tempdb..sysobjects where id = OBJECT_ID('tempdb..#tCmn') and type='U' ) drop table #tCmn
create table #tidx (id int IDENTITY(0,1) PRIMARY KEY, id0 int, i int, g int )
create table #tCmn (id int IDENTITY(0,1) PRIMARY KEY, m int, n int, e varchar(4000) )
CREATE INDEX index_tCmn_mn ON #tCmn( m, n )
CREATE INDEX index_tidx_g ON #tidx( g )
declare @tc_gi int, @tc_m int
DECLARE @cursor_tg CURSOR
DECLARE @cursor_tg2 CURSOR
SET @cursor_tg = CURSOR FORWARD_ONLY READ_ONLY FOR
select str(i,4),s from #tgout
OPEN @cursor_tg
FETCH NEXT FROM @cursor_tg INTO @tc_i, @s1
WHILE @@FETCH_STATUS = 0
BEGIN
delete from #tidx
SET @cursor_tg2 = CURSOR FORWARD_ONLY READ_ONLY FOR
select g.i,cast(substring(@s1,g.i*4+1,4) as int)n, g.n m
from #g g where cast(substring(@s1,g.i*4+1,4) as int)>0
OPEN @cursor_tg2
set @s2 =''; set @sx1 =''; set @sx2 =''
FETCH NEXT FROM @cursor_tg2 INTO @tc_gi, @tc_n, @tc_m
WHILE @@FETCH_STATUS = 0
BEGIN
if not exists(select * from #tCmn where m=@tc_m and n=@tc_n )
begin -- .do Cm,n to add
-- Cm,n (m中取n的组合算法)
declare @cm int, @cn int, @cd int, @ca int, @strExp varchar(4000), @va char(4)
set @cm =@tc_m; set @cn=@tc_n
set @strExp = space( @cn*4 ); set @cd =1; set @ca =1
while(1=1) -- Loop:a(1....n)
begin
-- // (XLoop:)b ( V(a-1)+1.... m-n+a )
if @cd=1
if @ca<=1
set @va =1
else
set @va = cast( substring(@strExp, (@ca-1) *4-3,4) as int) +1
else
set @va = cast( substring(@strExp, @ca *4-3,4) as int) +1
set @strExp = stuff(@strExp, @ca *4-3, 4, str(@va,4) )
set @cd =-1
if( @va > @cm-@cn+@ca )
if(@ca<=1)
BREAK -- exit Loop: finish
else
set @ca = @ca -1
else
if(@ca>=@cn)
begin
-- export data
insert #tCmn(m,n,e) values( @cm,@cn,@strExp)
end
else
begin
set @ca = @ca +1
set @cd =1
end
end
-- End of Cm,n
end
select IDENTITY(int,1,1) as i, id id0 into #tid0
from @tsrc t,#g g where t.c1=g.c1 and t.c2=g.c2 and g.i=@tc_gi
insert into #tidx(i,id0,g) select i,id0,@tc_gi g from #tid0
drop table #tid0
set @s2 = @s2+ '+str(t'+cast(@tc_gi as varchar)+'.id,4)'
set @sx1 = @sx1 +'(select id,e from #tCmn where m='+cast(@tc_m as varchar)+' and n='+cast(@tc_n as varchar)+')t'+cast(@tc_gi as varchar)+','
set @sx2 = @sx2 +' when '+cast(@tc_gi as varchar)+' then t'+cast(@tc_gi as varchar)+'.e'
FETCH NEXT FROM @cursor_tg2 INTO @tc_gi, @tc_n, @tc_m
END
CLOSE @cursor_tg2
set @s2 = 'select '''+@tc_i+'''+'+@s2+',y.id0 from '
set @sx2 = '(select x.g,x.i,x.id0 from #tidx x,#g g where cast(substring('''+@s1+''',g.i*4+1,4) as int)>0 and x.g=g.i)y where CHARINDEX(str(y.i,4),case y.g'+@sx2+' end)>0'
-- 按照解的组合从源中提取声母-韵母对,按照m中取n的组合,再各声母-韵母对交叉,得到该组中的所有解。
insert into #tout(grp,id0) exec(@s2 + @sx1 + @sx2 )
-- select str( t(@g.i1).id,4)+str( t(@g.i2).id,4)+...,y.id0 from
-- (select id,e,(@g.i1) g from @tCmn where m=@? and n=@?)t(@g.i1),
-- (select id,e,(@g.i2) g from @tCmn where m=@? and n=@?)t(@g.i2),
-- .....,
-- (select x.g,x.i,x.id0 from #tidx x,#g g where cast(substring(a.s,g.i*4+1,4) as int)>0 and x.g=g.i)y
-- where CHARINDEX(str(y.i,4), y.g:t(@g.i?).g?t(@g.i?).e)>0
FETCH NEXT FROM @cursor_tg INTO @tc_i,@s1
END
CLOSE @cursor_tg
DEALLOCATE @cursor_tg
DEALLOCATE @cursor_tg2
update #tout set c1= t.c1,c2=t.c2
from @tsrc t , #tout o
where t.id=o.id0
select count(DISTINCT grp) from #tout
select * from #tout order by grp, id0
drop table #tc1
drop table #tc2
Top
54 楼yaozw_mountain(山林)回复于 2005-08-17 09:11:51 得分 0
/*
注:上面几贴是相连的
-- 这里得到的与以前提供算法的解集相同(7)
3 3 l i 0 0 0 0 0
1 4 p an 0 0 0 0 0
2 5 p ao 0 0 0 0 0
0 8 b an 0 0 0 0 0
10 0 p i 1 1 0 0 0
8 1 b ao 1 1 0 0 0
4 2 l an 1 1 0 0 0
6 4 p an 1 1 0 0 0
11 0 p i 1 2 0 0 0
9 1 b ao 1 2 0 0 0
7 4 p an 1 2 0 0 0
5 7 l an 1 2 0 0 0
12 2 l an 2 1 0 0 0
14 4 p an 2 1 0 0 0
16 5 p ao 2 1 0 0 0
18 6 b i 2 1 0 0 0
15 4 p an 2 2 0 0 0
17 5 p ao 2 2 0 0 0
19 6 b i 2 2 0 0 0
13 7 l an 2 2 0 0 0
26 0 p i 3 0 1 0 0
22 2 l an 3 0 1 0 0
24 5 p ao 3 0 1 0 0
20 8 b an 3 0 1 0 0
27 0 p i 3 0 2 0 0
25 5 p ao 3 0 2 0 0
23 7 l an 3 0 2 0 0
21 8 b an 3 0 2 0 0
*/
Top
55 楼prcgolf(小鸟)回复于 2005-08-17 14:09:06 得分 0
upTop
56 楼yaozw_mountain(山林)回复于 2005-08-17 15:40:09 得分 0
一点改进, 提高速度:
CREATE INDEX index_tidx_i ON #tidx( i )
.......
/*
select IDENTITY(int,1,1) as i, id id0 into #tid0
from @tsrc t,#g g where t.c1=g.c1 and t.c2=g.c2 and g.i=@tc_gi
insert into #tidx(i,id0,g) select i,id0,@tc_gi g from #tid0
drop table #tid0
*/
insert into #tidx(i,id0,g)
select -1 i, id id0, @tc_gi g
from @tsrc t,#g g where t.c1=g.c1 and t.c2=g.c2 and g.i=@tc_gi
set @i=0
update #tidx set @i=i=@i+1 where i=-1
Top
57 楼softj(天地客人<最近很迷茫>)回复于 2005-08-17 18:01:45 得分 0
从楼上到楼下,一共走了几个小时,看明白一点,可是更好的方法还没有想出!先UP一下吧,
若能想出好方法,一定来贴!Top
58 楼herr()回复于 2005-08-20 11:29:54 得分 0
UPTop
59 楼herr()回复于 2005-08-20 14:48:52 得分 0
j9988(j9988) 根据你的方法 有点问题 看到了联系啊 我给你Q 留言了Top
60 楼herr()回复于 2005-08-20 15:30:59 得分 0
yaozw_mountain(山林) 速度不可取10分钟 都不不来,我的数据5万 去60条Top
61 楼yaozw_mountain(山林)回复于 2005-08-22 14:21:03 得分 0
herr():
完成第一步:得到所有解组合集,
不执行第二步(m中取n的组合,循环中Cm,n和drop table #tid0比较费时)
用时是多少?Top

