取得数据集交集的最优方法

SP12345678902 2011-03-09 10:40:10
大虾们好

我最近遇到一个问题

VB代码,从两个数据库中取得结果集

然后取这两个结果集的交集
Recordset1结果集形如
restaurant0001
restaurant0005
restaurant0009
restaurant0010
....
Recordset2结果集形如
restaurant0001
restaurant0005
restaurant0006
restaurant0011
....

因为是2个数据库,所以直接在SQL上面做文章我认为已经不可能

我已经想到2个方法,但是效率都不高
1.Recordset1和Recordset2取出来之后,利用拿Recordset1的每一个去Recordset2里面去查,找到就把它塞到Recordset3中
这是双重循环,偏偏我的数据量很大,每个结果集估计5000条数据,效率不高
2.利用Recordset自带的Recordset2.find "restaurantcode = ''",拿Recordset1的每一个去Recordset2里面去find ,找到就把它塞到Recordset3中,已经试过了,这个效率也很差,估计也是双重循环

请高手指点迷津,定送分
...全文
519 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
king06 2011-03-09
  • 打赏
  • 举报
回复
[Quote=引用楼主 yunmingqu 的回复:]
2.利用Recordset自带的Recordset2.find "restaurantcode = ''",拿Recordset1的每一个去Recordset2里面去find ,找到就把它塞到Recordset3中,已经试过了,这个效率也很差,估计也是双重循环
[/Quote]
用filter方法,然后看有没有记录. 用的时候最好把记录集设置为断开连接的.
赵4老师 2011-03-09
  • 打赏
  • 举报
回复
仅供参考
#include <algorithm>
#include <iostream>
#include <functional>
#include <cstring>
using namespace std;
int main() {
char *Alphabet = "abcdefghijklmnopqrstuvwxyz" ;
char *Vowels = "aeiou" ;
char *AlphaNum = "0123456789abcdef" ;
char result[45] ;
char *last ;

int lenA = strlen(Alphabet) ;
int lenV = strlen(Vowels ) ;
int lenAN = strlen(AlphaNum) ;

cout << "Alphabet = " << Alphabet << endl ;
cout << "Vowels = " << Vowels << endl ;
cout << "AlphaNum = " << AlphaNum << endl ;

cout << "\nusing non-predicate versions" << endl ;

//non-predicate set_difference
last = set_difference(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_difference(Alphabet, AlphaNum) = " << result << endl ;

//non-predicate set_intersection
last = set_intersection(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_intersection(Alphabet, AlphaNum) = " << result << endl ;

//non-predicate set_symmetric_difference
last = set_symmetric_difference(Alphabet, Alphabet+lenA,
Vowels , Vowels +lenV,
result) ;
*last = 0 ;
cout << "set_symmetric_difference(Alphabet, Vowels) = " << result << endl ;

//non-predicate set_union
last = set_union(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_union(Alphabet, AlphaNum) = " << result << endl ;

cout << "\nusing predicate versions" << endl ;

//predicate set_difference
last = set_difference(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_difference(Alphabet, AlphaNum) = " << result << endl ;

//predicate set_intersection
last = set_intersection(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_intersection(Alphabet, AlphaNum) = " << result << endl ;

//predicate set_symmetric_difference
last = set_symmetric_difference(Alphabet, Alphabet+lenA,
Vowels , Vowels +lenV,
result , less<char>()) ;
*last = 0 ;
cout << "set_symmetric_difference(Alphabet, Vowels) = " << result << endl ;

//predicate set_union
last = set_union(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_union(Alphabet, AlphaNum) = " << result << endl ;

return 0 ;
}
王二.麻子 2011-03-09
  • 打赏
  • 举报
回复
上面的直接在2个数据库操作不知道效率,

我觉得得到recordset1和recordset2的时候用排序,
然后用recordset1的每个记录去recordset2去找,
比如recordset1的一个记录a小于recordset2里面的一个记录b,那么a记录就不用继续比较了。
那么下次recordset1的下一个记录a+1就应该从recordset2的b记录开始比较,直到返回相等或者a+1记录大于b+n记录,下次a+2记录应该从b+n记录那里开始比较。

应该会比LZ所说的双重循环好很多。
chinaboyzyq 2011-03-09
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 yunmingqu 的回复:]

vb
sql server 2005
[/Quote]


SELECT *
FROM sjb
UNION
SELECT *
FROM OPENROWSET('SQLOLEDB', '127.0.0.1'; 'sa'; 'dg', master.dbo.sjb)


127.0.0.1改成远程服务器IP
vbman2003 2011-03-09
  • 打赏
  • 举报
回复
sql server 2005没用过
不过如此你的问题sql语句肯定能搞定...参考chinaboyzyq的语句,再看看T-SQL帮助即可
dbcontrols 2011-03-09
  • 打赏
  • 举报
回复
更好的办法?比如有没有不需要循环的办法?

[Quote=引用 7 楼 chinaboyzyq 的回复:]
SQL SERVER不在同一服务器上也可以用SQL语句实现。
[/Quote]
SP12345678902 2011-03-09
  • 打赏
  • 举报
回复
vb
sql server 2005
chinaboyzyq 2011-03-09
  • 打赏
  • 举报
回复
SQL SERVER不在同一服务器上也可以用SQL语句实现。
无·法 2011-03-09
  • 打赏
  • 举报
回复
要看什么数据库的吧,sql语句各个数据库都有所差异的,支持的也不都相同,不过基本都大同小异,楼上是在什么环境下?
dbcontrols 2011-03-09
  • 打赏
  • 举报
回复
跑题了吧,楼主在找交集.
这问题百思不得其解.有没有捷径?
chinaboyzyq 2011-03-09
  • 打赏
  • 举报
回复
[Quote=引用楼主 yunmingqu 的回复:]
因为是2个数据库,所以直接在SQL上面做文章我认为已经不可能
[/Quote]
这句话你就说错了,你可连接一个数据库同时与别一个数据库一起操作。方式大体如下:
比如你连接打开pubs中的表sjb同时操作master中的sjb,两个表名可以不同。

SELECT *
FROM sjb
UNION
SELECT *
FROM master..sjb

SP12345678902 2011-03-09
  • 打赏
  • 举报
回复
我现在做的是一个很大的系统,由很多耦合的模块组成,两个数据库分属不同的模块
真的不能合并数据啊
无·法 2011-03-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 sysdzw 的回复:]

两个数据库不可以合并吗?表可以不合并,这样就可以sql语句操作了。

就你上面的来说个人觉得将两个结果都保存下来(数组或者字符串),然后用在vb中处理,循环一次就行了。
例如Recordset1保存在字符串s中,各个数据用逗号隔开。Recordset2保存在数组a(5000)中,循环5000次,检索每个数据在s中是否存在,存在的话就输出。
[/Quote]“Recordset2保存在数组a(5000)”,这个可以不用保存到数组,因为rs.movenext实际就已经在访问各个数据了。
无·法 2011-03-09
  • 打赏
  • 举报
回复
两个数据库不可以合并吗?表可以不合并,这样就可以sql语句操作了。

就你上面的来说个人觉得将两个结果都保存下来(数组或者字符串),然后用在vb中处理,循环一次就行了。
例如Recordset1保存在字符串s中,各个数据用逗号隔开。Recordset2保存在数组a(5000)中,循环5000次,检索每个数据在s中是否存在,存在的话就输出。
咸清 2011-03-09
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 chinaboyzyq 的回复:]

用第1个查询的结果做第2个查询的条件,则得到是就是交集:
SQL code

SELECT *
FROM OPENROWSET('SQLOLEDB', '127.0.0.1'; 'sa'; 'dg', master.dbo.sjb)
Rowset_1
WHERE (日期 IN
(SELECT 日期
FROM sjb))
[/Quote]

在数据库里面做是最好的了,因为有索引,所以会很快。
离开数据库在本地处理的话,就不要讲什么效率了!
最少也是
O(N*logN)
showjim 2011-03-09
  • 打赏
  • 举报
回复
要么排序后归并,要么哈希
lxq19851204 2011-03-09
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 yunmingqu 的回复:]
楼上说的对

但是我不知道客户的数据库构架,所以数据库语句直接完成实现不了
[/Quote]
既然不知道客户的数据库构架,那你是怎么取的数据的?
chinaboyzyq 2011-03-09
  • 打赏
  • 举报
回复
[Quote=引用 22楼 yunmingqu 的回复:]

我不知道客户的数据库构架,所以数据库语句直接完成真的实现不了

[/Quote]
你的两个记录集是怎么来的?你不用连接数据库?也不用打开数据表?
SP12345678902 2011-03-09
  • 打赏
  • 举报
回复
楼上说的对

但是我不知道客户的数据库构架,所以数据库语句直接完成实现不了
chinaboyzyq 2011-03-09
  • 打赏
  • 举报
回复
用第1个查询的结果做第2个查询的条件,则得到是就是交集:

SELECT *
FROM OPENROWSET('SQLOLEDB', '127.0.0.1'; 'sa'; 'dg', master.dbo.sjb)
Rowset_1
WHERE (日期 IN
(SELECT 日期
FROM sjb))
加载更多回复(6)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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