关于按一定规则进行统计数目的算法(例如按月)--SQL篇

 ■在这里我们数据表结构假设为如下这样:
(当然实际情况一般都是由多张表关联起来的,我们姑且把实际的子结果集做为表)
统计对象表1(假定名称为User,User可以是表,子查询结果集,视图)
1。id         --自增列(KEY)
2。name       --用户名称
3。logindate  --登录日期
4。did        --部门标识

统计对象表2(假定名称为devn,devn可以是表,子查询结果集,视图)
1。did         --部门标识(KEY)
2。dname       --部门名称

■假设我们要求出如下格式的报表:
____________________________________________________________________
部门名 | 用户名 | 一月份登录次数 | 二月份登录次数 | 三月份登录次数 |
──────────────────────────────────

■解决方案

㈠思路估计就是千篇一律:从数据库中查询出这样结构的数据,
  然后交给写报表处理就行了,本文也没有脱离这个思路,
  既然是基于数据库的,写查询语句就开始了。
㈡按照上面报表格式的要求,比较直接的一种SQL写法如下:
(SQL中的函数是ACCESS中的,其他数据库要做对应修改)
select
d.dname, --部门名称
u.name,  --用户名称
(select count(id)
  from User m1
  where m1.did=d.did and format(m1.logindate,'yyyy/mm')='2009/01'
) as month1, --一月份登录次数
(select count(id)
  from User m2
  where m2.did=d.did and format(m2.logindate,'yyyy/mm')='2009/02'
) as month2, --二月份登录次数
(select count(id)
  from User m3
  where m3.did=d.did and format(m3.logindate,'yyyy/mm')='2009/03'
) as month3  --三月份登录次数
from devn d
left join user u on d.did=u.did
这段SQL通过在ACCESS中验证是可行的,这样查询出来的数据因为
结构与报表所需的数据能直接对应上,所以几乎不用其他处理就
交给报表程序来处理了,从我们实现的角度来说,的确是很方便的方法。
如果数据量比较小的情况,已经满足需求了。但如果数据量稍微大点,
执行这个查询就慢很多了,在ACCESS中验证结果是这样的:
User,devn中数据量在20000条左右,在我计算机上执行这个
查询需要15分钟,在其他数据库上没有做测试,但估计也快不到哪去。
■SQL优化
分析上面的SQL的执行复杂度,
设user数据量为l,devn数据量为m,统计的月数为n
每一个部门对应的每一个用户统计都要进行n次
所以这个SQL中仅统计(count部分)的算法复杂度粗略为:l*n
从这个算式上可以看出,只要任何一个数目增一,就是n倍级递增。
要优化这个SQL,关键部分就是在这个统计上尽量减少这种翻倍递增复杂度。
按这个思路,把复杂度改进成呈线性增长而不是翻倍,改进后的SQL如下:
select
d.dname,      --部门名称
u.name,       --用户名称
u.logindate,  --登录月份
u.cnum        --登录次数
from devn d left join (
 select name,did,
iif((format(logindate,'yyyy/mm')<='2009/07'),'2009/07',format(logindate,'yyyy/mm')) as logindate,
count(id) as cnum from user
group by name,did,iif((format(logindate,'yyyy/mm')<='2009/07'),'2009/07',format(logindate,'yyyy/mm'))
) u on u.did=d.did
这个SQL查询在同样20000条记录上在ACCESS中测试是2秒左右,这个查询
结果集条数是多了些,但执行效率提升了很多倍,现在存在的问题是

查询出来的数据在结构上不能直接交给报表处理的,
查询出来的结果集需要在程序里进行表结构导置处理,由于在性能上的要求,
这种倒置也是存在一定的优化算法的,关于程序里的算法,放到下一节里来说明了。

 

下篇(关于按一定规则进行统计数目的算法(例如按月)--应用程序篇)

http://blog.csdn.net/linaren/archive/2009/11/05/4771232.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值