如何查找两个相同结构的DBF表中不相同的记录?

aroffice 2013-04-08 11:41:50
有两个结构一样的表,有个别记录不同,需要把不同的记录提取出来。
如A表
id xm xb
01 A01 1
02 A02 1
03 A03 1
04 A04 2
05 A05 2
06 A06 2
07 A07 1
08 A08 1
09 A09 1
10 A10 2

B表
id xm xb
01 A11 1
02 A02 1
03 A03 2
04 A04 1
05 A05 2
06 A06 2
07 A07 1
08 A08 1
09 A09 1
10 A10 2

对比A表和B表后到不相同记录的C表
id zd btz1 btz2
01 xm A01 A11
03 xb 1 2
04 xd 2 1

...全文
707 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
安荣 2013-04-14
  • 打赏
  • 举报
回复
zd="XM"

adbf ="X:\个人数据\VF\111\表a.DBF"
bdbf ="X:\个人数据\VF\111\表b.DBF"


TF=0
CLOSE DATABASES
use
DELETE FILE dbjg.DBF
DELETE FILE ta1.DBF
DELETE FILE ta2.DBF
DELETE FILE tb1.DBF
DELETE FILE tb2.DBF

USE &adbf IN 1
zdshu=AFIELDS(Stru1,1)
DIMENSION zdmsz(zdshu)
USE &bdbf IN 2
zdshu2=AFIELDS(Stru2,2)
CLOSE DATABASES

IF zdshu!=zdshu2
	MESSAGEBOX("结构不相同!",64,'信息提示')
	TF=1
ELSE
	FOR tc=1 TO zdshu
		zdmsz(tc)=Stru1(tc,1)
		IF zdmsz(tc)==zd THEN
			zdh=tc
		ENDIF
		FOR tr=1 TO 15
			IF Stru1(tc,tr)==Stru2(tc,tr)
			ELSE
				MESSAGEBOX("结构不相同!",64,'信息提示')
				TF=1
				EXIT
			ENDIF
		ENDFOR
		IF TF=1
			EXIT
		ENDIF
	ENDFOR
ENDIF


IF TF=0 THEN
	SELECT * FROM &adbf WHERE &zd  NOT IN(SELECT &zd FROM &bdbf) INTO TABLE ta1
	COPY STRUCTURE  TO dbjg FIELDS &zd
	USE dbjg
	ALTER TABLE dbjg ADD zdm C(20)
	ALTER TABLE dbjg ADD dbz C(100)
	DELETE FILE dbjg.BAK

	SELECT * FROM &bdbf WHERE &zd  NOT IN(SELECT &zd FROM &adbf) INTO TABLE tb1
	CLOSE DATABASES
	USE dbjg.DBF
	APPEND FROM ta1.DBF
	REPLACE ALL dbz WITH "B表不包含"
	APPEND FROM tb1.DBF
	REPLACE ALL dbz WITH "A表不包含" FOR dbz=" "
	REPLACE ALL zdm WITH zd
	DELETE FILE ta1.DBF
	DELETE FILE tb1.DBF

	SELECT * FROM &adbf WHERE &zd   IN(SELECT &zd FROM &bdbf) INTO TABLE ta2
	SORT TO ta1 ON &zd
	SELECT * FROM &bdbf WHERE &zd   IN(SELECT &zd FROM &adbf) INTO TABLE tb2
	SORT TO tb1 ON &zd
	CLOSE DATABASES


	USE ta1
	jj=&zd
	DIMENSION  btjl(3)
	FOR i=1 TO RECCOUNT()
		SKIP 1
		IF jj==&zd THEN
			btjl(1)=&zd
			btjl(2)=zd
			btjl(3)="A表记录重复"
			DELETE
			INSERT INTO dbjg FROM ARRAY btjl
		ELSE
			jj=&zd
		ENDIF
	ENDFOR
	PACK
	jlshu=RECCOUNT()
	DIMENSION  sja(jlshu,zdshu)
	COPY TO ARRAY sja REST
	CLOSE DATABASES

	USE tb1
	jj=&zd
	DIMENSION  btjl(3)
	FOR i=1 TO RECCOUNT()
		SKIP 1
		IF jj==&zd THEN
			btjl(1)=&zd
			btjl(2)=zd
			btjl(3)="B表记录重复"
			DELETE
			INSERT INTO dbjg FROM ARRAY btjl
		ELSE
			jj=&zd
		ENDIF
	ENDFOR
	PACK
	DIMENSION  sjb(jlshu,zdshu)
	COPY TO ARRAY sjb REST
	CLOSE DATABASES
	
	DELETE FILE ta1.DBF
	DELETE FILE ta2.DBF
	DELETE FILE tb1.DBF
	DELETE FILE tb2.DBF

	USE dbjg
	DIMENSION btjl(3)
	FOR tr=1 TO jlshu
		FOR tc=1 TO zdshu
			IF sja(tr,tc)!=sjb(tr,tc) THEN
				btjl(1)=sja(tr,zdh)
				btjl(2)=zdmsz(tc)
				btjl(3)="A表和B表值不同"
				mtype=VARTYPE(sja(tr,tc))
				DO CASE
				CASE  mtype$"CM"
					btjl(3)="A:"+sja(tr,tc)+"    B:"+sjb(tr,tc)
				CASE  mtype$"NY"
					btjl(3)="A:"+STR(sja(tr,tc),15,3)+"    B:"+STR(sjb(tr,tc),15,3)
				CASE mtype$"DT"
					btjl(3)="A:"+TTOC(sja(tr,tc))+"    B:"+TTOC(sjb(tr,tc))
				ENDCASE
				INSERT INTO dbjg FROM ARRAY btjl
			ENDIF
		NEXT
	NEXT

ENDIF

USE dbjg
BROWSE
aroffice 2013-04-13
  • 打赏
  • 举报
回复
已经找到办法了,先用SELECT查找关键字段相互包含和不包含的, SELECT * FROM &adbf WHERE &zd NOT IN(SELECT &zd FROM &bdbf) INTO TABLE ta1 SELECT * FROM &adbf WHERE &zd IN(SELECT &zd FROM &bdbf) INTO TABLE ta2 ………………………… 再排序,排除重复记录。将数据赋值到数组内,用for循环一一对比,将对比结果放到新的一个表中。
十月鹰飞 2013-04-11
  • 打赏
  • 举报
回复
select id,name,a.xb,b.xb from a.dbf inner join b.dbf on a.id=b.id where a.xb<>b.xb
aroffice 2013-04-08
  • 打赏
  • 举报
回复
引用 1 楼 fspc1985 的回复:
最简单就是把两个表合到一起,然后查找出只有一条的记录。SELECT先自己想想吧~~~
有很多字段的,我这只是举的一个例子,每个字段重复的数据也有很多。
fspc1985 2013-04-08
  • 打赏
  • 举报
回复
最简单就是把两个表合到一起,然后查找出只有一条的记录。SELECT先自己想想吧~~~
WWWWA 2013-04-08
  • 打赏
  • 举报
回复
上述代码假设ID唯一且两表结构一致
WWWWA 2013-04-08
  • 打赏
  • 举报
回复
CREATE CURSOR T (ID C(2),ZDM C(10),btz1 C(10),btz2 C(10)) &&保存不同记录的临时表 CREATE CURSOR TA (ID C(2),XM C(3),XB C(1)) CSTA=[01,A01,1;02,A02,1;03,A03,1;04,A04,2;05,A05,2;06,A06,2;07,A07,1;08,A08,1;09,A09,1;10,A10,2] FOR I=1 TO ALINES(AA,CSTA,[;]) =ALINES(AAA,AA(I),[,]) INSERT INTO TA VALUES(AAA(1),AAA(2),AAA(3)) ENDFOR CREATE CURSOR TB (ID C(2),XM C(3),XB C(1)) CSTB=[01,A11,1;02,A02,1;03,A03,2;04,A04,1;05,A05,2;06,A06,2;07,A07,1;08,A08,1;09,A09,1;10,A10,2] FOR I=1 TO ALINES(BB,CSTB,[;]) =ALINES(BBB,BB(I),[,]) INSERT INTO TB VALUES(BBB(1),BBB(2),BBB(3)) ENDFOR EE=AFIELDS(AA,'TA') FOR I=1 TO EE STORE "SELECT " TO ASQLA,ASQLB IF UPPER(AA(I,1))<>'ID' ASQLA=ASQLA+"'"+AA(I,1)+"' as zd,id,"+AA(I,1)+" FROM ta INTO CURSOR qta" &ASQLA ASQLB=ASQLB+"'"+AA(I,1)+"' as zd,id,"+AA(I,1)+" FROM tB INTO CURSOR qtB" &ASQLB ASQLC="INSERT INTO T SELECT a.ID,A.ZD,A."+AA(I,1)+",b."+AA(I,1)+" FROM qta a LEFT JOIN qtb b ON a.id=b.id WHERE A."+AA(I,1)+"<>B."+AA(I,1) &ASQLC ENDIF NEXT
十豆三 2013-04-08
  • 打赏
  • 举报
回复
引用 5 楼 apsiar 的回复:
引用 4 楼 lygcw9602 的回复: SQL code?123456789101112131415161718192021222324252627282930CREATE CURSOR T (ID C(2),ZDM C(10),btz1 C(10),btz2 C(10)) &amp;&amp;保存不同记录的临时表CREATE CURSOR TA (ID C(2),XM C(……
给出的代码是支持多个字段的,要对比的字段顺序要一样。
lygcw9602 2013-04-08
  • 打赏
  • 举报
回复
CREATE CURSOR TB (ID1 C(2),XM C(3),XB C(1)) 改为 CREATE CURSOR TB (ID C(2),XM C(3),XB C(1))
十豆三 2013-04-08
  • 打赏
  • 举报
回复

*-- VFP9.0
Create Table A表 (Id Varchar(10),xm Varchar(10),xb Varchar(10))
Insert Into A表 Values ('01','A01','1')
Insert Into A表 Values ('02','A02','1')
Insert Into A表 Values ('03','A03','1')
Insert Into A表 Values ('04','A04','2')
Insert Into A表 Values ('05','A05','2')
Insert Into A表 Values ('06','A06','2')
Insert Into A表 Values ('07','A07','1')
Insert Into A表 Values ('08','A08','1')
Insert Into A表 Values ('09','A09','1')
Insert Into A表 Values ('10','A10','2')

Create Table B表 (Id Varchar(10),xm Varchar(10),xb Varchar(10))
Insert Into B表 Values ('01','A11','1')
Insert Into B表 Values ('02','A02','1')
Insert Into B表 Values ('03','A03','2')
Insert Into B表 Values ('04','A04','1')
Insert Into B表 Values ('05','A05','2')
Insert Into B表 Values ('06','A06','2')
Insert Into B表 Values ('07','A07','1')
Insert Into B表 Values ('08','A08','1')
Insert Into B表 Values ('09','A09','1')
Insert Into B表 Values ('10','A10','2')

Create Table C表 (Id Varchar(10),zd Varchar(10),btz1 Varchar(10),btz2 Varchar(10))

CompareTable('A表','B表')
Select C表
Browse

Function CompareTable
	Lparameters tcTable1,tcTable2
	Use (tcTable1) Again In Select('_T1') Alias _T1
	Use (tcTable2) Again In Select('_T2') Alias _T2
	Select '_T2'
	Scan
		Select '_T1'
		Execscript('Locate For _T1.'+Field(1,'_T1')+'=_T2.'+Field(1,'_T2'))
		If Found()
			For lnI=2 To Fcount('_T2')
				If Evaluate('_T1.'+Field(lnI,'_T1'))<>Evaluate('_T2.'+Field(lnI,'_T2'))
					Insert Into C表 Values (Transform(Evaluate('_T2.'+Field(1,'_T2'))),Field(lnI,'_T2'),Transform(Evaluate('_T1.'+Field(lnI,'_T1'))),Transform(Evaluate('_T2.'+Field(lnI,'_T2'))))
				Endif
			Endfor
		Else
			Insert Into C表 Values (Transform(Evaluate('_T2.'+Field(1,'_T2'))),Field(1,'_T2'),'',Transform(Evaluate('_T2.'+Field(1,'_T2'))))
		Endif
	Endscan
Endfunc
lygcw9602 2013-04-08
  • 打赏
  • 举报
回复
前提是你的这两个表结构必须完全一样。
lygcw9602 2013-04-08
  • 打赏
  • 举报
回复
速度不敢保证,上述代码应该能达到你的要求。你可以试试!
aroffice 2013-04-08
  • 打赏
  • 举报
回复
引用 4 楼 lygcw9602 的回复:
SQL code?123456789101112131415161718192021222324252627282930CREATE CURSOR T (ID C(2),ZDM C(10),btz1 C(10),btz2 C(10)) &&保存不同记录的临时表CREATE CURSOR TA (ID C(2),XM C(3),XB C(1))CSTA=[0……
,谢谢,有一个问题,这个只是我写的一个例子,我需要比较的表有很多字段,有很多记录的。
lygcw9602 2013-04-08
  • 打赏
  • 举报
回复
CREATE CURSOR T (ID C(2),ZDM C(10),btz1 C(10),btz2 C(10)) &&保存不同记录的临时表
CREATE CURSOR TA (ID C(2),XM C(3),XB C(1))
CSTA=[01,A01,1;02,A02,1;03,A03,1;04,A04,2;05,A05,2;06,A06,2;07,A07,1;08,A08,1;09,A09,1;10,A10,2]
FOR I=1 TO ALINES(AA,CSTA,[;])
=ALINES(AAA,AA(I),[,])
INSERT INTO TA VALUES(AAA(1),AAA(2),AAA(3))
ENDFOR

CREATE CURSOR TB (ID1 C(2),XM C(3),XB C(1))
CSTB=[01,A11,1;02,A02,1;03,A03,2;04,A04,1;05,A05,2;06,A06,2;07,A07,1;08,A08,1;09,A09,1;10,A10,2]
FOR I=1 TO ALINES(BB,CSTB,[;])
=ALINES(BBB,BB(I),[,])
INSERT INTO TB VALUES(BBB(1),BBB(2),BBB(3))
ENDFOR

SELECT TA
SCAN
SCATTER TO AC
SELECT TB
SCAN FOR RECNO([TB])=RECNO([TA])
SCATTER TO AD
FOR I=2 TO ALEN(AC)
IF NOT (AD(I)==AC(I))
INSERT INTO T VALUES (TA.ID,FIELD(I,[TB]),AC(I),AD(I))
ENDIF
ENDFOR
ENDSCAN
ENDSCAN
SELECT T
BROWSE


查询结果图
xuzuning 2013-04-08
  • 打赏
  • 举报
回复
想了一个笨办法 1、 select * from A表 union select * from B表 into table tmpa tmpa 中就存有 A表 的全部记录和 B表 中与 A表 不相同的记录 2、删除 tmpa 原 A表 的记录 delete tmpa where recon()<reccount(A表) 3、对B表如法炮制 select * from B表 union select * from A表 into table tmpb delete tmpb where recon()<reccount(B表) 4、合并 tmpa、tmpb 就是需要的结果

2,749

社区成员

发帖
与我相关
我的任务
社区描述
VFP,是Microsoft公司推出的数据库开发软件,用它来开发数据库,既简单又方便。
社区管理员
  • VFP社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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