2007年的78,我的工作是完成车辆管理系统的需求分析和设计,期间的一个问题捆扰了我很久,此刻终于有时间将问题以及解决方案记录下来。

 
我们以需求(问题)的产生到问题的解决为轴线谈起吧。在车辆管理系统里,在费用方面涉及到固定费用和变动费用,我对它们的定义是:固定费用,即在固定时间里不会发生变动的车辆费用,如保险费、年检费、GPS费等。变动费用,即车辆日常维护和运作中根据实际情况而产生的费用,如换胎费、加油费、运费等。公司的决策层需要对车辆的盈利情况有很好的了解,即车辆毛利分析,需求便由此产生,变动费用可以很好的根据所依赖的单据来统计,比如维修费,可以根据维修单单号(如MT200708003)将其涉及的费用(如换胎费)采用SQL中的CASE语法可以将其轻松的按列表的形式表现,调度费用(即车辆营运产生的业务费用,如运费、维修费、加油费),亦可根据到调度单单号(如AT200708002)采用SQL中的CASE语法将其轻松的按列表的形式表示。显然车辆每单产生的应收应付、车辆的毛利(运费其他变动费用)在列表中,可以表现的一目了然,但对于完整的车辆成本分析,显然少考虑了固定费用,并且固定费用占了车辆成本的很大部分。

那么怎么将固定费用很好的表现在车辆毛利分析里呢?
   方案一.将固定费用分摊到每单涉及的费用中?个人认为没有这个必要。抛开技术实现复杂度不谈,就业务单据来说,单据的数量是随着业务的产生的不断增加的,试想,上月每单的保险费是
100,那么本月因单据的增加,上月每单的保险费是不是要是少于100了呢,所以在本月来看,上月每单的固定费用成本反应的是不是不准确了呢?
   方案二.将固定费用按月分摊到每车上呢?我想这是合理的,因为每年的月份数是固定的,都是
12个月,并且所有固定费用都是按月的整数倍来计算的,比如保险费按年,即12个月、季检费按季度,即3个月。所以将固定费用分摊到车辆每月成本中,每月车辆的固定费用成本就是不变的了,亦保证了车辆毛利分析的准确性。

解决思路定来了,从技术上又怎么来解决呢,即怎么样将固定费用分摊到车辆按月成本分析列表中呢?采用SELECT统计是一个不错的选择。用固定费用/所承担的月份数即可。可是又怎么固定费用和变动费用展现在一个列表里呢?SQLUNION便能解决此问题,既

SELECT NULLCASE WHEN固定费用=”固定费用项目” THEN固定费用/月数 ELSE O END

UNION

SELECT CASE WHEN 变动费用 =”变动费用项目” THEN … ELSE O ENDNULL

至此,车辆毛利分析所有遇到的问题看似都已解决,可到现在为什么还未涉及本文主题SQLFANCTION呢?

   我们继续分析,车辆毛利分析必须要能按时间来筛选啊!是必须实现按月份来查询的,这样实现好象也没有问题,只需在SELECT变动费用时,加上WHERE 时间=某月既可。但是这么做却是决策层所不能接受的,因为他们想要的是在一个列表里,车辆毛利分析反应的不仅仅是某车某月的情况,而是某车从营运以来或者多月的情况清晰可见。在SELECT固定费用时也加上WHERE 时间=某月不就解决问题?答案是否定的。因为固定费用只有开始时间和结束时间,比如2007/01/012007/12/30,那么我们按开始时间来WHERE 时间=5月,固定费用是不是查不出来了呢!?到这里问题似乎进入了无解决之境,我也开始迷茫

  放弃非我所本能,要是能将固定费用按它的开始时间和结束时间分摊成连续的月份数据,并放在一个表里,是不是完全可以满足车辆按任意月份查询的需求了呢?答案是肯定的,但如此处理,同样的数据保存在两张表里,总有些不妥,因为会给其它功能的实现带来不必要的麻烦。这时SQL FANCTION显灵了,是不是可以将固定费用用FANCTION在形成车辆成本时动态生成连续的月份数据呢?是的,个人觉得此方法很妙(^-^自恋一下),因为FANCTION根据现有的数据返回的表是临时的,不需要改变现有表结构或是增加表,更不会影响其他功能的设计。而且很好的解决了问题,实现了需求。当然,FANCTION动态生成数据要牺牲一定的性能,并且随着固定费用数据的增加,性能的负面影响也就越大,因为在动态生成表时,必须遍历所有固定费用。但是只让FANCTION计算近两年的数据,是不是解决了固定费用日益增多的问题呢?值的注意的是,如果数据库存在由MS SQL SERVER 迁移的情况,FANCTION就不能用了,因为FANCTION只有MS SQL SERVER才支持。
  总结:在采用SELECT统计数据时,大多情况下是将多行数据汇总起来,但在这里却反其道而行,将行数据拆分成多行,并很好的解决了问题。这就是所谓的逆向思维吧,正如某电影所说:赌马,分析的不是哪匹马会赢,而是统计哪些马不会赢。所以在思考问题时,弄清楚自己为什么会这么想,思考的依据是什么,思路是什么,是很有意义的,因为只有在我们清楚的知道自己思考的线路时,方能清晰的逆向而行。