VFP 中的 SQL SELECT 语句使用要点(4)

2019-03-22 10:12

2 2

很明显,有些记录重复了几遍。temp1.aa 中的虽然只有 1 个 2,但 temp2.aa 有 3 个 2,所以结果就会有 1*3 = 3 个 2 了。如果 temp1.aa 而 2 个 2 的话,那结果就会有 2*3 = 6 个 2 了。

知道了这一点,在做多表链接查询的时候很有用。你要考虑第一、二个链接后的结果跟第三个表链接时,会不会出现这种情况?如果有,那是不是你想要的?如果有,那怎么处理?有些朋友说做这个命令的结果中有些记录会比正确的结果大几倍,就要看看是不是出现了这种重复算的情况。

学会了链接,在开始做之前,先要说一个很重要的问题:在视图设计器来看多个表的联接关系,它们之间的链接是用一条线连接起来的,看起来就象一串糖葫芦。如果一个表同时和三个表联接,那看起来就象一支分叉的树枝了,那这种情况结果就不对了。大家可能不明白我在说什么,我举个例子大家就会明白了。

有一个产品表、一个进货明细表、一个出货明细表,现在的要求是要求产品表中所有的产品的进、出情况,也就是把三个表象 join 命令那样合成一个表,如果没有相应的进、出记录,也照样列出来但不计较null值。刚开始学的朋友很可就会这样做:

1、 在设计器里添加这三个表;

2、 然后用产品表中的产品编号分别与其它二个表左链接,这样产品表中就有二个链接(也就是二条线了);

3、 然后把三个表的字段都做为输出字段。

但结果呢?不对。只有一个表的记录出现在结果中,即使把四种链接类型都试一下,结果都是不对的。

为什么呢?我估计是以下原因:如果产品表只与进货表链接的话,系统根据产品表和进货表的联接关系,以产品表为左表,和进货这个右表组成一个临时结果,然后又以临时表为左表,再去找进货表的右边表。而进货表的右边没有表,这时系统就停止链接,交给where去过滤了。但现在产品表同时跟二个表左联接,系统会自动选其中一个先进行链接,链接结果出来后,这个临时结果的右边就没有表了,系统就停止链接动作了。剩下的出货表、退货表都还没链接,所以那个表等于没用。

解决的方法是:进货表用进货表的产品编号全链接产品表,然后产品表又用产品表的产品编号全链接出货表,进、货表的顺序可以调过来,但产品表一定要在中间,且两个链接类型都是全链接,否则结果都不对。

这样的链接情况,在设计器里按链接中的各个表的左右顺序排起来,很直观的:就是一串!没有分叉。这个方法的实现过程就是:

进货表全链接产品表,即使某种产品没有进货,但得出来的结果也一样有这个记录,只是它的进货内容是null值。然后这个临时结果又跟出货表全链接,这次的结果就前一步差不多,有出货内容的记录就有出货数量,否则就是null值。因为没有分叉,所以全部表都链接进去了,结果也就对了(当然如果链接类型错了,结果也是不对的)。

看了刚才那个问题之后,还有一个问题也要说一下。在刚才那个例子中,如果产品表中某个产品编号出现了重复,有N个记录的编号相同,而在进货表里这个编号的记录也出现M个,这样一来,结果就有点不同了。首先在进货表跟产品表的全链接结果里,这个编号就会出现N*M次,就不是一次了。然后这个临时表再去跟出货表全链接时,即使这个编号在出货表里出现一次,但在最后的链接结果中,这个编号还是会出现N*M次,那它的出货记录也重复了N*M次了。如果现在要 sum() 出货记录的话,那出货数量就会放大了 N*M 倍了,进货记录也不准了。所以如果产品表中的编号有重复的话,那结果就很可能会不对了。

但产品表的编号没有重复,那结果就一定会正确呢?也未必。大家试一下,假设进货表和产品表的编号 \001\都是只出现一次,但出货表中就出现了二次。那最后的结果中\还是出现了二次,二次的产品名称、进货数量都是相同的,只是出货数量不同而已。如果这时 sum(),结果还是不对。

所以如果想在多表链接后进行 sum() 之类的汇总操作,使用以上的方法是不行的。解决方法是使用 union,用它来将进货的汇总情况跟出货的汇总情况合起来,从而避免互相干扰。这方面的做法请看以后的 union的使用 一节吧。

--------------------------------------------------------------------------------

第四节 union 的使用

union 可以将几条 SQL SELECT 命令合成一条,要求是这几条命令生成的表,在字段个数、字段类型、字段长度、字段顺序上都完全一样。以下面这些情况下,一般都要使用它的:

一. 把几个结构完全一样的表的记录都加在一起,最后生成的表,在结构上跟那几个表也完全一样,但记录数就是那几个表的记录数的总和。

举个例子:我想统计一段时间内的提货、进货情况,最后生成的表是这样的:

产品编号(cpbh) 产品名称(cpmc) 提货数量(thsl) 进货数量(jhsl)

先用二条命令分别计算提货数量和进货数量,生成二个临时表,最后用 union 合成一个表。

sele thdmx.cpbh,sum(iif(isnull(thsl),0,thsl)) as thsl; from cpk left join thdmx ; on cpk.cpbh=thdmx.cpbh ; grou by cpbh ; into curs temp1

sele jhdmx.cpbh,sum(iif(isnull(jhsl),0,jhsl)) as jhsl; from cpk left join jhdmx ; on cpk.cpbh=jhdmx.cpbh ; grou by cpbh ; into curs temp2

现在 temp1 和 temp2 的格式跟最后的结果有点不同,都是少了一个提货数量(进货数量),不能直接使用 union 联合。所以我们要人为给每个临时表加个对应的字段,命令如下:

sele cpbh,thsl,10000-10000 as jhsl ; from temp1 ; union ;

sele cpbh,0 ,jhsl ; from temp2 ; into curs temp3

在每节 SQL SELECT 命令,都加了一个字段,它的值都是零(没有嘛,当然是零啦)。这样一样,每节 SQL SELECT 命令生成的表在结构上就完全一样了,就可以使用 union 了。大家试一下,如果都不加个字段的话,那虽然不会出错,但结果的结构就跟要求不一样了。

在上面那条命令,每一节都可以使用 \来给字段重新起名。如果在第一节使用了 \,则以后的则可能不用了。否则的话,就是最后使用 \的那节才起作用,前面的都无效了。

temp3 出来了,就可以使用分级合并了。

sele cpbh,sum(thsl) as thsl,sum(jhsl) as jhsl ; from temp3 ; grou by cpbh ; into curs temp4

现在这个 temp4 就是最后正确的结果了。

做了这么多步,大家应该明白这类联合统计的命令是怎样做的吧。但精益求精的我们是不会满足的,还可以对上面的那么多个步骤进行简化:

sele thdmx.cpbh,sum(iif(isnull(thsl),0,thsl)) as thsl,10000-10000 as jhsl; from cpk left join thdmx ; on cpk.cpbh=thdmx.cpbh ; grou by cpbh ; union ;

sele jhdmx.cpbh,0, sum(iif(isnull(jhsl),0,jhsl)) ; from cpk left join jhdmx ; on cpk.cpbh=jhdmx.cpbh ; grou by cpbh ; into curs temp1

sele cpbh,sum(thsl) as thsl,sum(jhsl) as jhsl ; from temp1 ; grou by cpbh ; into curs temp2

大家看一下,使用了union 是不是更简洁了?这里只统计进、出情况,如果再加上退、报废等情况,采用第一种方法就要使用五条命令,产生 6 个临时表。而采用第二种方法,无论再加多少种情况,都只需 2 条命令和 2 个临时表就可以。

二. 从一个表的数据中生成分类汇总的信息

表的数据数下:

入库日期 材料类别 材料名称 规格材质 单位 数量 1998.02.23 钢材 不等边角钢 L125*80*10 Q235 t 0.052 1998.02.23 钢材 不锈管 Φ10*2 1Cr18Ni9T t 0.875 1998.02.23 钢材 不锈管 Φ108*4 1Cr18Ni9T t 0.013 1998.02.23 钢材 不锈管 Φ108*4.5 1Cr18Ni9T Kg 27.6 1998.02.23 钢材 不锈管 Φ14*2 1Cr18Ni9T t 2.761 1998.02.23 钢材 不锈管 Φ14*3 1Cr18Ni9T t 0.104 1998.02.23 钢材 不锈管 Φ159*5 1Cr18Ni9T t 0.11 1998.02.23 钢材 不锈管 Φ159*5.5 1Cr18Ni9T Kg 108 1998.02.23 钢材 不锈管 Φ57*3.5 1Cr18Ni9Ti t 0.126 1998.02.23 钢材 不锈管 Φ60*4 1Cr18Ni9Ti t 0.33 1998.04.29 化工产品 喷漆 瓶 2 1998.05.26 化工产品 喷漆 瓶 10 1998.04.29 化工产品 氧气 瓶 156 1998.05.26 化工产品 氧气 瓶 119 1998.04.28 化工产品 乙炔 瓶 94 1998.03.18 化工产品 氩气 瓶 19 1998.04.23 化工产品 氩气 瓶 20 1998.01.01 有色金属 黄铜板 δ =0.75 Kg 4.5 1998.01.01 有色金属 黄铜板 δ =2 Kg 7.6 1998.01.13 有色金属 黄铜棒 Φ13 Kg 4.5 1998.01.01 有色金属 黄铜棒 Φ35 Kg 5.2 1998.01.13 有色金属 黄铜管 Φ10*2 Kg 2.5 1998.01.13 有色金属 黄铜管 Φ12*3 Kg 2.5 1998.01.13 有色金属 黄铜管 Φ6*1 Kg 5.2


VFP 中的 SQL SELECT 语句使用要点(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:民办幼儿园特色发展浅探

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: