Posted on 2005-08-03 17:27
橙子 阅读(1607)
评论(13) 编辑 收藏 网摘
今天下午遇到了一个问题,就是对两个动态查询出来的记录集(注意是动态查询),判断二者其中一个字段是否包含相同的数据,当然,数据类型是一样的。着实为这个问题头疼了一番
我的数据库中的字段是较大的,包含了几十万行的数据,如果遍历两个记录集,天哪,这可是乘法原理呀,这样数量级的排列所产生的运算次数为:P(100000,100000),一个10万的全排列。效率有多高就知道了。
怎样才能找到一个性能较高的办法呢,把检索后的数据放入内存表,这时我想到了一个办法,就是对象的hashcode的计算方式,呵呵,如果能够为这个记录集找到一个唯一值,就像对象的HashCode,这样是不是就可以了呢,就像两个对象的比较一样。果然,试过之后,这样的问题就解决了,当然产生这个唯一值的算法是有待于研究的。
CREATE PROCEDURE [dbo].[ct_AddNewSection]
@lose_section_id int ,
@cell_id_list varchar(2000),
@errstr varchar(500) output
AS
set nocount on
declare @indexValue int,@pos int
declare @sectionid int

set @pos = 1
set @indexValue = 1
set @indexValue = charindex(',',@cell_id_list,@indexValue)
--两个内存表用来存储动态查询出的记录集
declare @t_cellid table (cellid int) --定义临时表
declare @t_sectionid table (sectionid int, tempval bigint ) --定义临时表,第一个字段是为了将多个类似的记录集放在一个表里与@t_cellid做比较

while @indexValue > 0
begin
set @cellID = substring(@cell_id_list,@pos,(@indexValue-@pos))
if @cellID <>''
begin
insert into @t_cellid(cellid)values(@cellID)
end
set @pos = @indexValue+1
set @indexValue = charindex(',',@cell_id_list,@indexValue+1) -----更改@indexValue
end
---下面就是主要的处理了,取要判断数据相同字段的hashcode
declare @hashvalue bigint
select @hashvalue = sum(CellID^3080|10880) from @t_cellid
insert into @t_sectionid select LogicSectionID,sum(CellID^3080|10880) from tb_CellOfLogicSection group by LogicSectionID

if exists (select * from @t_sectionid where tempval = @hashvalue)
begin
select @sectionid=sectionid from @t_sectionid where tempval = @hashvalue
set @errstr = '已经有包含相同组合存在,编号'+cast(@sectionid as varchar(10))
return
end 这样只要判断这个@hashvalue就可以了
Feedback
是否可以通过修改数据库的结构来实现。
例如:建立一个联合的查询语句。
其实修改数据库结构也不是办法,毕竟可能的记录集是动态查询出来的,与数据库的结构其实并没有什么直接的联系,这样作的处理是把记录集当作对象来处理,实现的对象的hashcode的方法。
是不是还有更好的方法呢,欢迎评论!
既然欢迎评论我就不客气了。
我觉得你的程序很搞笑。
1.无法验证结果的正确性;
2.与对象毫无瓜葛,十八杆子都打不着;
3.一定有更简便、效率更高的算法。
我觉得可以用联合查询..因为你要查询的表中肯定是对相同的字段值做比较的嘛..
感觉还存在缺陷,可能只能作为初步的筛选,还需要进一步验证
不过看到用哈希的时候还是觉得眼前一亮
呵呵,谢谢
对于“双鱼座”所言:
还需要进一步验证这个是肯定的,但是我到是认为只要两个记录集中有不相同的数据存在那只要选择的算法足够强,就能够保证hashcode的唯一性,否则hash的作用也就没有了。
还有我到是不认为这是初步筛选,因为这中间目的就是为了寻找好的算法保证唯一
如果用联合查询,我还是有些不是很明白,怎么样做联合查询呢?要求数据集中的数据相同,是否可以讲的详细一些呀
先把两个表按照那个字段排序,再用Cursor比较不就行了,肯定会很快
呵呵,关键是另一个记录集里面有sectionid这个字段,也就是说要比较的是第一个记录集里面的数据和第二个记录集里面的数据每个sectionid的一部分,如下面所示
set1
cellid
1001
1002
2003
set2
cellid sectionid
1001 1
1002 1
2003 1
2256 1
1001 5
1002 5
2003 5
从这里看需要的是看看在set2里面的每个sectionid是否有与set1相同的组合存在,只有5这个组合才与set1相同,而1呢就不相同了,呵呵,这样排序再用cursor怎么处理呢,我到是有些迷茫了
table1:A, B
table2:C,D
select A,B
from
(
select A,B,'Table1' state
from table1
union all
select C,D,'Table2'
from table2
) x
group by A,B
having count(*) > 1
这样就可以了
上面的SQL可以得出 你所共同的集合
当然要得出 判断是否有重复的结果可以这样
select case when count(*) > 0 then 'true' else 'false' end as Result
from
(
select A,B
from
(
select A,B,'Table1' state
from table1
union all
select C,D,'Table2'
from table2
) x
group by A,B
having count(*) > 1
) y
:)
动态查询结果是可以生成 #table的
呵呵 原理与上面所述的一样
其实这句就可以得到相同的结果集
select A,B
from table1
union
select C,D
from table2
其它的就不多讲了
但最开始的方法适用的范围则更广
当然速度也较之要慢一些
:)
的确发现了其中的问题,但是如果使用复杂一些的算法应该可以避免重复的。如md5