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

2019-03-22 10:12

sele cpbh,sum(thdmx.thsl) as thsl,100000-100000 as jhsl ; from thd join thdmx ; on thd.thdbh=thdmx.thdbh ; grou by cpbh ; union ;

sele cpbh,0,sum(jhdmx.jhsl) ; from jhd join jhdmx ; on jhd.jhdbh=jhdmx.jhdbh ; grou by cpbh ; orde by cpbh ; into curs temp1

如果看了上面的解释,应该可以理解每一节 SQL SELECT 命令的意思。这里要说的是:

1、union 要求前后两节 SQL SELECT 命令产生的表,在结构上要完全一样,包括字段的顺序也要一样。所以为了达到这个要求,在第一节,就要人为建立一个字段 jhsl,而在第二节命令,也要建立一个字段 thsl 以对应。

2、用 SQL SELECT 产生的表,它不象 crea table 那样可以直接指定字段的类型、长度,而是在根据生成的临时表中第一个记录的长度来确定的。所在在第一节,如果不使用 100000-100000 而是直接使用 0,这样产生的 jhsl 这个字段,它的长度就只有 2 个字节了。所以只有使用这种方法,才能使得这个字段的长度有 7 字节。在字符串也有这样情况,如果第一个记录的长度是 12 个字节,那以后的记录中,超过 12 个字节的内容就会给它去掉,这就是为什么有时在结果表中会出现字符串不完整的情况。解决方法也差不多,在字段列表那里人空加几个空格去。

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

第二节 on、where、having的不同之处

这里有个例子来比较一下过滤条件放在 on、where、having 会有什么的不同之处:

表 recdbf 内容如下: 还有一个 tempyf 的辅助表,记录 12 个月 日期 性质 yf

2000年7月3日 特大 1 2000年7月9日 特大 2 2000年9月3日 特大 3 1999年3月2日 一般 4 1999年3月4日 一般 5 2000年1月3日 一般 6 2000年2月1日 一般 7 2000年2月3日 一般 8 2000年3月4日 一般 9 2000年8月7日 一般 10 2000年11月2日 一般 11 1999年2月3日 重大 12 2000年2月3日 重大 2000年5月2日 重大 2000年8月9日 重大

现在的要求是要统计 yy 年中十二个月的事故记录中,一般、重大、特大各有多少。如果没有事故的,则以 0 表示。

我们首先要把今年的记录过滤出来,过滤条件就是 YEAR(日期)=?yy,然后按月份分组统计。

这样一来,如果某个月没有事故记录,那分组后的结果就没有该月的记录,这样不符合要求。所以做个临时表 yf,该表有十二个记录,分别代表 1 至 12 月,用它来左联接 recdbf,这样,即使某个月没有事故记录,也会出现在最后的结果当中,只是以 null 的形式出现罢了。但我们可以使用 isnull() 函数来判断它是不是 null 值,如果是,则 iif() 会把它变为 0,然后交与 sum() 进行统计。

总体设想搞好后,现在就开始写命令了。开始之前先说明:tempyf.yf = MONTH(recdbf.日期)是 yf 表与 recdbf 表的联接条件,是一定要在on的,这个不在讨论范围。我们要讨论的是 YEAR(日期) = ?yy 这个条件放在什么地方会有什么样的结果。

首先把过滤条件放在 on 这里:

SELECT tempyf.*,;

SUM(IIF(ISNULL(recdbf.日期).OR.AT(\一般\性质)=0,0,1)) AS 一般,; SUM(IIF(ISNULL(recdbf.日期).OR.AT(\重大\性质)=0,0,1)) AS 重大,; SUM(IIF(ISNULL(recdbf.日期).OR.AT(\特大\性质)=0,0,1)) AS 特大; FROM tempyf LEFT OUTER JOIN recdbf ;

ON tempyf.yf = MONTH(recdbf.日期).AND.YEAR(日期) = ?yy; GROUP BY tempyf.yf

其中 yy=2000,表示统计 2000 年的数据。

用 where 的命令如下:

SELECT tempyf.*,;

SUM(IIF(ISNULL(recdbf.日期).OR.AT(\一般\性质)=0,0,1)) AS 一般,; SUM(IIF(ISNULL(recdbf.日期).OR.AT(\重大\性质)=0,0,1)) AS 重大,; SUM(IIF(ISNULL(recdbf.日期).OR.AT(\特大\性质)=0,0,1)) AS 特大; FROM tempyf LEFT OUTER JOIN recdbf ; ON tempyf.yf = MONTH(recdbf.日期); GROUP BY tempyf.yf ;

where YEAR(日期) = ?yy &&注意,条件从 on 移到这里来了 用 having 的命令如下:

SELECT tempyf.*,;

SUM(IIF(ISNULL(recdbf.日期).OR.AT(\一般\性质)=0,0,1)) AS 一般,; SUM(IIF(ISNULL(recdbf.日期).OR.AT(\重大\性质)=0,0,1)) AS 重大,; SUM(IIF(ISNULL(recdbf.日期).OR.AT(\特大\性质)=0,0,1)) AS 特大; FROM tempyf LEFT OUTER JOIN recdbf ; ON tempyf.yf = MONTH(recdbf.日期); GROUP BY tempyf.yf ;

having YEAR(日期) = ?yy &&注意,条件从 on 移到这里来了 on 的结果如下,这是正确的:

YF 一般 重大 特大 1 1 0 0 2 2 1 0 3 1 0 0 4 0 0 0 5 0 1 0 6 0 0 0 7 0 0 2 8 1 1 0 9 0 0 1 10 0 0 0 11 1 0 0 12 0 0 0

用 where 的结果如下:

YF 一般 重大 特大 1 1 0 0 2 2 1 0 3 1 0 0 5 0 1 0 7 0 0 2 8 1 1 0

用 having 的结果如下:

YF 一般 重大 特大 1 1 0 0 2 2 2 0 5 0 1 0 7 0 0 2 8 1 1 0 9 0 0 1 11 1 0 0

各位看到有什么不同吗?

on 是把先把 recdbf 中不是 2000 年的记录过滤掉,剩下的就是 2000 年的了,再用 tempyf 去和它们进行外联接,其结果可用:

sele tempyf.*,recdbf.日期 ; from tempyf left join recdbf ;

ON tempyf.yf = MONTH(recdbf.日期).AND.YEAR(日期) = ?yy; orde by yf

来查看,这个中间结果出来后,再用 isnull 把空值的记录变成 0 或 1,然后由 sum 去统计,结果就出来了。

而 where 呢:

1、 它是先把 tempyf 外联接 recdbf,相当于 sele tempyf.*,recdbf.* from tempyf left join recdbf on tempyf.yf=mont(recdbf.日期);

2、 然后把不是 2000 的记录过滤掉,这里要注意的是,如果某个月没有记录的话,那在第一个步骤后日期那里是 null 值,这当然不是 2000 的记录,所以就给这个条件给过滤出去了,所以下一步的 sum 之后就只剩下那有记录的那个月了,象 4、6 月等几个月就没有了;

3、 然后进行 sum(……)。

再看 having:

1、第一步和 where 一样;

2、 第二步不同,它是先 sum(),这里的 sum 可不管你是 1999 年还是 2000 的,先累加起来再说,这时,1999 和 2000 年的 2 月份都有\重大\这个记录,sum 的结果是 2,这里用第三个步骤去分辨这个 2 之中那个是 1999 年的,那个是 2000 的,这当然分不清啦,所以也错了;

3、 根据步骤 2 来把 2000 的过滤出来。


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

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

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

马上注册会员

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