4.3 表的排序与索引
排序与索引的概念及二者的区别。
重点:索引及其使用
4.3.1 表的排序
排序( SORT ):对表中的记录进行物理排序。
格式 : SORT TO < 新表文件名 > ON < 字段名 1>[[/A|/D][/C]]
[,< 字段名 2>[/A|/D][/C]…] [ASCENDING|DESCENDING]
[< 范围 >][FOR< 条件 >][WHILE < 条件 >][FIELDS < 字段名表 >]
功能:按给定的字段名值由大到小或由小到大的顺序对当前表文件重新排列,并生成一个新的表文件。
[ 例 ] 把 stud.dbf 中入学成绩大于 520 的,按入
学成绩从高到低排序,保存在 strxcj.dbf 中。 use stud
Sort to strxcj on 入学成绩 /d for 入学成绩 >520
use strxcj
list
[ 例 ] 把 stud.dbf 表按入学成绩(升序)、性别、
姓名均按降序排列,保存在 strxcj2.dbf 中。 use stud
Sort to strxcj2 on 入学成绩 /a, 性别 ,姓名 desc
use strxcj2
list
4.3.2 索引概述
1 .索引的概念
索引( INDEX ):对表中的记录进行逻辑排序。即另外形成一个索引关键表达式值与记录号之间的对照表,这个对照表就是索引文件。
索引文件是一个二维表,其中仅有二列数据:关键字值和记录的物理位置。关键字值是包含有字段的排序规则表达式,记录的物理位置指向关键字值在表中所在的物理位置。
例如,在表 4-1 的 Stud 表中,根据入学成绩的高低来建立索引文件。建立好的索引文件如表 4-2 所示。
记录号 学号 姓名 性别 出生日期 入学成绩 1 03083101 王文 男 09-20-81 510
2 02083106 李道 男 01-15-83 520
3 02083103 邓轩斌 男 11-28-78 524
4 02093108 王瑞姝 女 01-01-84 522
5 02093105 刘光辉 男 11-06-80 526
表 4-1 Stud 表中的记录
关键字(入学成绩)值 记录的物理位置 526 5
524 3
510 1
520 2
522 4
表 4-2 根据入学成绩字段建立的索引文件
注意:索引并未改变表中记录的物理位置,仅仅改变了表中记录的逻辑排序。但是,当用户将建立好的索引文件打开以后,记录的显示顺序或读取处理记录的顺序将会按照索引文件排列的记录顺序进行。这样大大提高了记录的检索速度。
可以为一个表同时建立多个索引文件,每个索引文件表示处理记录的不同顺序。
2. 索引文件的种类
单一索引文件 (.IDX )
复合索引文件 (.CDX)
索引文件 结构复合索引文件(与相关表文件同名)
非结构复合索引文件(与相关表文件不同名)
单一索引文件的内部结构如图 4-1 所示。单一索引文件的扩展名为 .IDX 。
关键字值入学成绩 记录的物理位置 522 4
508 6
… …
524 3
526 5
图 4-1 单一索引文件结构
复合索引文件的内部结构如图 4-2 所示。复合索引文件的扩展名为 .CDX 。
图 4-2 复合索引文件结构
11-28-78
…
06-09-83
01-01-84
关键字值2
1
…
3
5
物理位置1
3
…
5
4
物理位置2
510
…
520
526
关键字值1
……
03083101
…
02083106
02083103
关键字值 n
1
…
2
3
物理位置n
索引标识1
索引标识 2 索引标识 n
从图中可以看到复合索引文件可以由多个关键字值和其对应的多个记录的物理位置构成。每一个关键字值和其对应的记录的物理位置构成了一个索引标识( TagName )。在复合索引文件中,每一个索引标识等价于一个单一索引文件。换句话说,复合索引文件等价于多个单一索引文件。
结构复合索引文件的文件名称与相关的表同名,另外结构复合索引文件将随着相关表的打开而自动打开。
非结构复合索引文件的文件名称与相关的表不同名,另外非结构复合索引文件不会随着相关表的打开而自动打开,要由用户自行打开。
索引与排序的不同点:
② 生成的文件不是 .dbf 文件,不需占用单独的工作区;
③ 索引不改变原表文件中各记录的物理顺序。
① 索引文件占用空间小;
3. 索引的类型索引可分为 4种类型:
索引
主索引
候选索引不允许在指定字段和表达式中出现重复值的索引。一个表可以建立多个候选索引。
不允许在指定字段和表达式中出现重复值的索引。只有数据表才能建立。
惟一索引 只在索引文件中保留第一次出现的索引关键字值。
普通索引
存储在 .cdx结构复合索引文件中,与表文件同时打开和关闭。
可存储在 .cdx 独立复合索引文件和 .idx 单索引文件中
4.3.3 建立索引文件
VFP中,为表建立索引可以采用两种方法来完成:
一、菜单方式:在表设计器中通过直观的操作来建立索引
二、命令方式:使用 INDEX命令来建立索引
格式: INDEX ON < 索引表达式 > TO < 单索引文件名 >
功能:对当前表建立一个索引文件或增加索引标识。
TAG < 索引标识名 > [OF < 复合索引文件名 >][FOR < 条件 >] [COMPACT] [ASENDING|DESCENDING] [UNIQUE][CANDIDATE][ADDITIVE]
说明:
( 1)若给出 TO < 单索引文件名 >子句,则建立一个单索引文件。
若给出 TAG < 索引标识 > [OF < 复合索引文件名 >] ,则建立一个结构复合索引文件,或为已建立并打开的复合索引文件增加索引标识。
OF < 复合索引文件名 > 选项用于指定非结构复合索引文件的名字,省略此选项时,表示建立结构复合索引文件。
( 2) COMPACT 参数仅在建立单一索引文件时使用。该参数用于为单一索引文件获得压缩处理快速存取索引文件技术的支持,从而大大提高单一索引文件的使用效率。( 3 ) ASCENDING|DESCENDING 参数用于指定复合索引文件的某一索引标识是按照升序( ASCENDING )还是降序( DESCENDING )方式进行排序。( 4 ) UNIQUE 参数用于建立唯一索引。也就是说对于拥有相同关键键值的若干条记录而言,只有第一条记录才会列入该索引文件中,其他具有此关键值的所有记录都将被排除在该索引文件之外。( 5) CANDIDATE 参数用于建立候选索引。( 6 ) ADDITIVE 参数用于在建立新的索引文件时,已打开的其他索引文件仍保持打开状态。
【例】对 stud 表按入学成绩升序建立索引文件 Use stud index on 入学成绩 to cja List
Use stud index on - 入学成绩 to cjd List
【例】对 stud 表按入学成绩降序建立索引文件
建立单一索引文件
单一索引文件只能按照升序方式进行排列。
建立结构复合索引
(在 INDEX命令中使用 TAG <标识名> 参数 )
【例】对 stud.DBF :① 用学号作关键字,建立结构复合索引文件,标识名为 xh
Use stud
Index on 学号 tag xh
② 用姓名作关键字,建立结构索引文件,标记名为 xm
Use stud
Index on 姓名 tag xm
在建立复合索引文件时,可使用[ ASCENDING/ DESCENDING]参数指定某一索引标识是按照升序(ASCENDING) 还是降序 (DESCENDING) 方式进行排序。【例】 若要为 Stud 表根据入学成绩字段建立结构复合索引文件,索引标识为 Et ,并且希望按降序方式排列,那么应执行的命令为:
USE Stud
INDEX ON 入学成绩 TAG Et DESCENDING
【例】对 stud.DBF ,用入学成绩 , 出生日期 , 姓名作关键字,建立结构索引文件,标记为 strcx 。
Use studIndex on str( 入学成绩 ) +dtoc( 出生日期 )+ 姓名 tag strcx
【例】对 stud 表按学号建立非结构复合索引文件,文件名为 scxh.CDX ,索引标识为 xh。
Use stud
index on 学号 tag xh of scxh
建立非结构复合索引
(在 INDEX 命令中使用 TAG<TagName> [OF<CDX 文件名 >]参数)
【例】 若要为 Student 表根据 entrancescore 字段建立单一索引文件(单一索引文件名为 Entr.IDX ),并且 USE Student
【例】若要为 Stud 表根据入学成绩字段建立单一索引文件(单一索引文件名为 en1.IDX ),希望只有满足入学成绩大于 520 这一条件的记录才会出现在索引文件的索引关键字值列表中,那么应执行命令:
Use stud
INDEX ON 入学成绩 TO En1.IDX FOR 入学成绩> 520
设置有条件的索引
【例】若要为 Stud 表根据出生日期字段建立单一索引文件(单一索引文件名为 nl.IDX ),并且该索引文件是唯一索引,那么应执行的命令:
Use stud
INDEX ON 出生日期 TO nl.IDX unique
设置惟一索引
【例】若要为 Stud 表根据学号字段建立结构复合索引文件(索引标识为 stuid ),并且该索引标识为候选索引,那么应执行命令:
Use stud
INDEX ON 学号 Tag stuid candidate
设置候选索引
4.3.4 索引文件的使用
命令格式: USE < 表文件名 > INDEX < 索引文件名表>
[ ORDER < 索引文件 > TAG <标记名> OF < 索引文件 >
[ ASCENDING | DESCENDING]
[ IN < 工作区 > ]
1. 打开索引文件 (1) 打开表文件的同时打开索引文件
功能:打开指定的表及其索引文件。
【例】 已知 stud.DBF 有 scxh.cdx( 标记名有 xh,xm) 、cja.idx 和 nl.idx 等索引文件。
Use stud index cja , nl , scxh
① 打开表文件时打开所有索引文件,并以 cja.idx 作为主索引文件,命令是:
Use stud index nl , cja , scxh order cja
或:
Use stud index cja, scxh, nl order tag xm of scxh
② 打开表文件时打开所有索引文件,并以 scxh.cdx 作为主索引文件,标记名为 xm,命令是:
【例】 已知 stud.DBF 有 scxh.cdx( 标记名有 xh,xm) 、cja.idx 和 nl.idx 等索引文件。
命令格式: SET INDEX TO [< 索引文件名表> ] [ADDITIVE]
(2) 在打开表后再打开索引文件
除结构复合索引能随着表文件的打开而打开外,其他索引文件必须用索引文件的打开命令来打开。
功能:在已打开表文件的前提下,打开指定的索引文件。
[ORDER < 索引文件 > |[TAG ] <标记名>
[ OF < 索引文件 > ] ]
[ ASCENDI
NG|DESCENDING]
Use stud
打开索引文件 cja.idx 和 nl.idx ,并用 nl作为主控制索引(主索引)。命令为:
Set index to nl, cja
【例】 已知 stud.DBF 有 scxh.cdx( 标记名有 xh,xm) 、cja.idx 和 nl.idx 等索引文件。
命令格式: SET ORDER TO [ < 索引文件顺序号 > |< 单索引文件名 >]
[TAG] <索引标记名> [OF < 复合索引文件 >]
2.确定主控索引
功能:指定表的主控索引文件或主控索引标识。
注:命令 SET ORDER TO 可以取消主控索引。
Use stud index cja
Set order to xh
【例】 已知 stud.DBF 有结构复合索引文件 (标记名有xh,xm) 、单索引文件 cja.idx 和 nl.idx 等,现要使用这些索引对 stud 表进行操作。
list
list
Set order to xm
list
Set order to
list
Use stud index cja
? recno( )
【例】 分析在已打开索引文件情况下记录指针的移动。
Go 3
skip
? Recno( )
Go top
? Recno( )
Go bottom
? Recno( )
作业 :
P86 : 题: 6 、 7 、 8 、 9 、 10 、 13 ( 1-1
0 )
4.3.4 索引文件的使用 索引的重要命令回顾 打开索引与控制索引的区别 索引查询 关闭索引 ( 恢复物理顺序 ) 删除索引 ( 文件和标识 ) 索引的更新
1. 索引的重要知识回顾 : 建立索引 : INDEX ON < 索引表达式 > TO < 单索引文件名 > INDEX ON < 索引表达式 > TAG < 索引标识名 > 索引表达式的规则 : 表达式的组成
打开索引与控制索引区别 (1) 新建的索引 (2) 打开索引 :SET INDEX TO < 索引标识或文件名表 > (3) 命令 :SET ORDER TO TAG < 索引标识或单索引文件名 >
单个字段( N 、 C 、 D型)
多个字段一般转换成 C 型
多个 N 型字段求和问题不转换。
STR()
DTOS()
DTOC()
例 : 以姓名降序排列的索引标识 XM 。
以生日升序排列建立单索引文件 SR.IDX 。
对 student.dbf 表显示总成绩最低的 5 名学。
先按性别再按年龄升序排列。
INDEX ON 姓名 TAG XM DESC
INDEX ON 生日 TO SR
INDEX ON 数学 + 外语 TAG SYWYLIST NEXT 5
INDEX ON 性别 +STR((DATE()- 生日 )/365) TAG XNL
LIST
例 :
以生日 SR 标识为控制索引 SET ORDER TO SR LIST 以 XNL 为控制索引 SET ORDER TO TAG XNL LIST
2. 索引查询(1) 条件查询与索引查询的区别 ( 顺序与折半 )(2) 索引查询命令SEEK < 表达式 >功能:指针定位于与表达式相同的第一记录上。说明: < 表达式 > 必须与索引关键字一致。
FIND < 字符串 >说明:字符型常数不用加引号。相关函数: EOF() FOUND() RECNO()
继续查询: SKIP
DISPLAY
索引查询实例 :
从 student.dbf 表显示总成绩为 132 的学生显示之 .
use student SET ORDER TO TAG SXWY FIND 132 &&SEEK 132 DISP 找姓名为”王平”的学生显示之 . SET ORDER TO TAG XM Find 王平 &&SEEK ‘ 王平’ disp
索引查询实例 :
从 student.dbf 表中找 84 年 9 月 5 日出生的学生 .
use student SET ORDER TO SR SEEK {^1984/09/05} display
3. 关闭索引文件 当关闭表文件时,同时关闭同一工作区中所有已打开的索引文件。此外,还有下列关闭索引文件的命令:
格式 1 : SET INDEX TO
格式 2 : CLOSE INDEX
功能:关闭当前工作区中除结构索引文件外的所有索引文件。
(1)删除索引文件
若用索引文件命令来删除索引文件,须遵循先关闭后删除的原则。
命令格式: DELETE file < 索引文件名 >
功能: 删除打开的单索引文件。
4.删除索引
(2)删除索引标识
命令格式: DELETE TAG ALL | < 索引标识名表 >
功能: 删除打开的复合索引文件的所有 (或指定 )索引标识。
5. 索引的更新
( 1) .自动更新
( 2) .重新索引
命令: REINDEX
打开的索引 ,都随记录内容更新而自动更新 .
更新表文件时 ,索引文件没打开的情况 , 用重新索引实现更新 .
4.4 表的统计与计算
命令格式: COUNT [< 范围 >] [FOR < 条件 >]
[TO < 内存变量名 >]
功能:统计当前打开的表文件在指定范围内满足条件的记录个数。
4.4.1 数据统计 1. 记录个数统计命令 COUNT
【例】统计 student.dbf 表中性别为’男’的记录数 , 并赋给内存变量 js 。Use student
Count for 性别 =‘男’ to js? js
格式: SUM [< 范围 >] [< 字段表达式 >] [FOR < 条件 >][TO < 内存变量名 >]
功能:对当前打开的表文件指定范围内满足条件的记录的数值型字段按指定的表达式求和,并把每一个表达式求和的结果一一对应地分别赋给指定的内存变量。
2. 字段值求和命令 SUM
【例】计算 student 表中男生数学的总和 , 并赋给内存变量 a1 。
Use student
Sum 数学 FOR 性别 =' 男 ' TO a1?a1
格式: AVERAGE [< 范围 >] [< 字段表达式 >]
[FOR < 条件 >] [TO < 内存变量名 >]
功能:对当前打开的表文件按指定范围、条件求指定字段的算术平均值,并把结果一一对应地分别赋给指定的内存变量。
3. 求平均值命令 AVERAGE
【例】求 student 表中男生数学的平均值 , 并赋给内存变量 a2 。Use student
AVERAGE 数学 FOR 性别 =' 男 ' TO a2
?a2
格式: CALCULATE [< 范围 >] [< 表达式表 >] [FOR < 条件 >][TO < 内存变量名表 >]
功能:对当前表文件中的数值型字段按指定范围、条件求记录数、平均值、最大值、最小值等计算,并可将计算结果存入内存变量或数组中。
4. 统计计算命令 CALCULATE
注: <表达式 >为以下函数的任意组合,各函数间用逗号隔开。
CNT () :统计记录数 AVG( < 数值表达式 >): 求 < 数值表达式 > 的算术平均值; MAX(< 数值表达式 >) :计算 < 数值表达式 > 的最大值; MIN(< 数值表达式 >) :计算 < 数值表达式 > 的最小值;
【例】求 student 表中数学最高分、最低分、平均分、人数。
Use student
Calc max( 数学 ), min( 数学 ), avg( 数学 ), cnt( )
Calc max( 数学 ), min( 数学 ), avg( 数学 ), cnt( ) for 性别 =' 女 '
格式: TOTAL ON < 关键字 > TO < 结果表文件名 >]
[FIELDS< 字段名表 >] [ < 范围 > ] [FOR < 条件 >]
功能:对当前打开的表文件按指定范围内满足条件的记录分类汇总求和。
1. 分类求和命令 TOTAL
注:① < 关键字 >字段必须已排序或索引(应为主索引) ;
② <字段名表 >必须是数值型字段 .
4.4.2 数据统计
③ 凡未参与求和的字段,生成记录的字段为相应第一个记录的字段值 .
【例】对 STUDENT.dbf 表分部门进行统计。
Use STUDENT
Index on 性别 tag XBTotal on 性别 to xbtot Use xbtot List