背景
因业务系统需要支持一些简单的考勤功能,好在公司有现成并且成熟的商业OA系统供参考,当然,只是功能参考而已,并无任何源码。
其中让我比较好奇的是,公司OA系统的考勤日统计是怎么做的?当然,好奇的同时,我还需要在自身的业务系统复刻此功能。
如图,此时间段,我还未入职,却一样能统计我的考勤情况,至于为什么是23条记录,也就是23天?去除休息日8天可不就剩23天!
也就是说不管有没有实际入职,有没有实际考勤打卡,系统会一天不落的统计职工每天的考勤情况,并且支持分页显示。
思考
初步探索
如果需要实现这种效果,能直接想到的似乎就如下1种方法:
- 根据查询的时间范围后台动态生成数据,并且使用假分页返回数据。
但此种方法很显然不可取,有以下弊端:
- 代码复杂度高
- 不利于查询,排序
- 不利于环保(因为跑起来费电)
进阶
比如输入 时间范围:2023-08-01至2023-08-31,将此时间范围的31天生成31个日期到某一个临时表里面?利用数据库连表查询的笛卡尔积不就能实现此功能了吗?
确实能实现此功能,而且相比上面说的动态生成方法更靠谱,利于查询、排序,而且…更省电!
但同样的,动态生成日期到临时表同样不靠谱,10个用户查询总不能生成10个临时表?用户要查询2年的数据,总不能就生成365x2=730条日期数据?用户每次的查询时间范围都不同,总不能每次生成一张新的临时表?
因此现在的问题变成:“如何减少生成临时表的次数,如何减少生成日期的次数”
这个似乎简单,不用临时表,那我直接生成一张辅助表,这张表提前生成过去10年,未来10年每一天的日期数据 365*20年=7300条日期数据。能完美解决这个需求!
一个系统能用10年也是烧高香了,似乎够用了,但我们要有点追求!
系统能不能定期检查一下辅助表中最大的日期和当前日期做对比,然后又生成未来5年10年的日期数据?
当然可以!机智如你!
最终解决方案
其实上面说的方法已经能很好的解决这个需求了,高效且方便,我猜公司OA系统用的就是此方法。
但年轻人就是不听劝,有没有更好的,或者不次于上面方法的方法?
也许有,个人认为!
只要生成一张如上的辅助表就行了,priority是按1步进的,不用生成具体的日期,利用数据库的date_add函数,根据用户查询的时间范围就能动态生成日期了,此种方法能减少辅助表的数据量,但由于使用数据库函数的关系,连表查询时效率较低。
综上所述,各有各的好,看你喜欢哪种。
总结
有些问题一旦点破,会让人觉得似乎如此的简单。
致谢名单:
1.公司OA系统