4、在数据统计上的比较
假设要根据EXPIRE_DATE字段,统计2005年每月到期的用户数。CHAR类型日期和DATE类型日期对应的统计SQL语句分别分析如下。
·CHAR类型日期
这种日期的表,要在日期字段上做统计是很方便的,下面的SQL语句统计出2005每月的T_USER记录:
| select substr(EXPIRE_DATE,5,2) MONTH,count(USER_ID) from T_USER where EXPIRE_DATE like '2005%'group by substr(EXPIRE_DATE,5,2) | 表 5 CHAR类型日期统计SQL
其中substr(EXPIRE_DATE,5,2)字符串处理函数获取日期的月份,如"20060102"通过该函数即得到"01"的月份值。而"EXPIRE_DATE like '2005%'"的条件式即过滤出所有2005年的数据,并且可以使用EXPIRE_DATE字段上的索引。
·DATE类型日期
对于DATE类型日期按月进行统计,乍一看,可以采用和CHAR类型日期相似的统计SQL语句:
| select extract(month from EXPIRE_DATE) MONTH,count(USER_ID) from T_USER where extract(year from EXPIRE_DATE ) = 2005 group by extract(month from EXPIRE_DATE) | 表 6 DATE类型日期统计SQL(全表扫描)
注:在Oracle中通过extract(<日期域名> from Date)函数获取日期的某特定日期域仁值。
但是仔细一分析,就会发现由于where条件式中对索引字段EXPIRE_DATE使用了extract()函数,因此EXPIRE_DATE上的索引在此统计SQL中将无法使用,所以该统计将引发一个全表扫描。
当然,你可以在EXPIRE_DATE字段上建立函数索引,但EXPIRE_DATE上的查询可以不仅仅只会用到extract()函数,一一为这些EXPIRE_DATE字段建立多个函数索引不但麻烦而且会影响T_USER上数据更新操作的性能。
当然,除了上式的统计方法外,还可以采用另外一种方法:
| select extract(month from EXPIRE_DATE) month,count(USER_ID) from T_USER where EXPIRE_DATE between to_date('20050101','yyyymmdd') and to_date('20051231','yyyymmdd') group by extract(month from EXPIRE_DATE) | 表 7 DATE类型日期统计SQL(使用索引)
表 7的方法可以使用EXPIRE_DATE字段上的索引,但又引入了一个我们前面已经提到过的不可避免的问题:必须按日期语义构造出开始和结束日期,以形成一个日期区间。在该例中,由于是对一整年进行统计,因而开始结束日期容易获得,如果是精确到月的日期区间,则需要计算出某月的最后一天,程序就复杂多了。但如果是CHAR类型日期的表,构造统计SQL语句,也易如反掌:如我们要统计200304~200402每月到期的用户数,可以通过以下SQL语句:
| select substr(EXPIRE_DATE,1,6) year_month ,count(USER_ID)from T_USER where EXPIRE_DATE between '20030400' and '20040299'group by substr(EXPIRE_DATE,1,6) | 即将开始日期以0补齐到8位,将结束日期以9补齐到8位。
|