您的位置:首页 > 数据库

采用SQL交集查询解决复杂模式物业收费统计

2012-02-16 14:40 204 查看
物业收费一般根据国家《物业管理条例》分为两种类型,

第一种:用户消耗的水电用量

在一个收费期段内,根据水表,电表计量的消耗量乘以单价,就是水电费。这种归类原因,主要是有计量消耗量数据的仪表。

第二种:用户期段内的服务费

例如:物业管理费,电梯费,卫生费等。这些费用计算的标准大多通过一个时间期段(如:每月、每天、每季度、每年等)还有用户住房的面积,住户人数等相关参数,来合理确定收费标准。

比如:卫生费由于住户的常住人口多,产生的生活垃圾等就多所以在收取卫生费的时候就要求将住户人数作为一个参数,这样收费对大多数用户来说更合理公平。

下面来谈下业务逻辑的数据库设计和实现。

基本信息表



查询视图



这里的设计内容比较多,大家都能设计出更好的。

我主要介绍下“视图_物业应交”这个视图的设计。

先提出点问题,算是引子

按照时间间隔收费,这个时间的间隔一般分为:“每月一次|每年一次|每天一次|每季度一次 ”四种,在实现SQL查询集合中就需要判断处理来解决,一种就是上一篇文章提到的IIF()函数。http://hi.baidu.com/chinameter/blog/item/00732b81f9b330c9bd3e1ef3.html

在由于收取的物业项目很有可能和住户的面积及常住人口数量有关系,所以设计这种嵌套的判断逻辑关系可读性,就变的异常复杂。

通过思考我打算采用交集(UNION)来实现,这样每一种可能定义的收费方式单独形式交集的一个子集,在把这些子集集合到一起也可以解决复杂嵌套判断逻辑结构复杂,不容易维护、升级等问题。



还有一个要点也等提一下。

在处理按照每年一次收费的时候,由于时间较长,一般都在自然年(就是新的一年开始后)来收取的,例如:暖气费大多在供暖前期,例如:11月15日供暖前就已经收取了。若要按照自然年在计算费用,肯定是有滞后性,不符合时间业务管理需求。要动态定义提前月份 和日期来实现这样的功能,才能和实际相结合有效的处理这样的特殊情况的业务逻辑中数据库查询的实现。

在一个保持参数信息表中定义连个字段“AMonth”和“ADay”来存储提前计算的月和日时间信息。

在子集中通过‍DateSerial()函数模拟 获得抽象自然年的日期(实际不是这个日期,仅获得这个日期值后,就可以根据自然年计算时间间隔)在通过 DateDiff()获得时间间隔。

‍‍



应用程序界面:





以下是全部SQL查询:

SELECT 地址,用户名称,编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间,DateDiff('m',开始时间,DATE()) as 数量, DateDiff('m',开始时间,DATE())*单价 AS 应收金额
FROM 视图_用户_物业项目
WHERE 收费周期='每月一次' and 乘面积 = 0 and 乘人数 = 0
UNION SELECT 地址,用户名称, 编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间, DateDiff('m',开始时间,DATE()) as 数量, DateDiff('m',开始时间,DATE()) * 单价 * 面积 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每月一次' and 乘面积 <> 0 and 乘人数 = 0
UNION SELECT 地址,用户名称 ,编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间, DateDiff('m',开始时间,DATE()) as 数量, DateDiff('m',开始时间,DATE()) * 单价 * 人数 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每月一次' and 乘面积 = 0 and 乘人数 <> 0
UNION SELECT 地址,用户名称, 编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间, DateDiff('m',开始时间,DATE()) as 数量, DateDiff('m',开始时间,DATE()) * 单价 * 人数 * 面积 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每月一次' and 乘面积 <> 0 and 乘人数 <> 0
ORDER BY 地址, 用户名称

UNION SELECT 地址,用户名称,编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间,DateDiff('d',开始时间,DATE()) as 数量, DateDiff('d',开始时间,DATE())*单价 AS 应收金额
FROM 视图_用户_物业项目
WHERE 收费周期='每天一次' and 乘面积 = 0 and 乘人数 = 0
UNION SELECT 地址,用户名称, 编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间,DateDiff('d',开始时间,DATE()) as 数量, DateDiff('d',开始时间,DATE()) * 单价 * 面积 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每天一次' and 乘面积 <> 0 and 乘人数 = 0
UNION SELECT 地址,用户名称 ,编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间, DateDiff('d',开始时间,DATE()) as 数量, DateDiff('d',开始时间,DATE()) * 单价 * 人数 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每天一次' and 乘面积 = 0 and 乘人数 <> 0
UNION SELECT 地址,用户名称, 编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间, DateDiff('d',开始时间,DATE()) as 数量, DateDiff('d',开始时间,DATE()) * 单价 * 人数 * 面积 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每月一次' and 乘面积 <> 0 and 乘人数 <> 0
ORDER BY 地址, 用户名称

UNION SELECT 地址,用户名称,编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间,DateDiff('q',开始时间,DATE()) as 数量, DateDiff('q',开始时间,DATE())*单价 AS 应收金额
FROM 视图_用户_物业项目
WHERE 收费周期='每季度一次' and 乘面积 = 0 and 乘人数 = 0
UNION SELECT 地址,用户名称, 编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间,DateDiff('q',开始时间,DATE()) as 数量, DateDiff('q',开始时间,DATE()) * 单价 * 面积 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每季度一次' and 乘面积 <> 0 and 乘人数 = 0
UNION SELECT 地址,用户名称 ,编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间,DateDiff('q',开始时间,DATE()) as 数量, DateDiff('q',开始时间,DATE()) * 单价 * 人数 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每季度一次' and 乘面积 = 0 and 乘人数 <> 0
UNION SELECT 地址,用户名称, 编号,用户_ID,电话,区名称,楼名称,面积,人数,时间,余额,物业名称,收费周期,单价,乘面积,乘人数,开始时间, DateDiff('q',开始时间,DATE()) as 数量, DateDiff('q',开始时间,DATE()) * 单价 * 人数 * 面积 AS 应收金额

FROM 视图_用户_物业项目
WHERE 收费周期='每季度一次' and 乘面积 <> 0 and 乘人数 <> 0
ORDER BY 地址, 用户名称

UNION SELECT 视图_用户_物业项目.地址,视图_用户_物业项目.用户名称,视图_用户_物业项目.编号,视图_用户_物业项目.用户_ID,视图_用户_物业项目.电话,视图_用户_物业项目.区名称,视图_用户_物业项目.楼名称,视图_用户_物业项目.面积,视图_用户_物业项目.人数,视图_用户_物业项目.时间,视图_用户_物业项目.余额,视图_用户_物业项目.物业名称,视图_用户_物业项目.收费周期,视图_用户_物业项目.单价,视图_用户_物业项目.乘面积,视图_用户_物业项目.乘人数,视图_用户_物业项目.开始时间, DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE()) as 数量 , DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE())*视图_用户_物业项目.单价 AS 应收金额
FROM 视图_用户_物业项目,system
WHERE 视图_用户_物业项目.收费周期='每年一次' and 视图_用户_物业项目.乘面积 = 0 and 视图_用户_物业项目.乘人数 = 0
ORDER BY 地址, 用户名称
UNION SELECT 视图_用户_物业项目.地址,视图_用户_物业项目.用户名称,视图_用户_物业项目.编号,视图_用户_物业项目.用户_ID,视图_用户_物业项目.电话,视图_用户_物业项目.区名称,视图_用户_物业项目.楼名称,视图_用户_物业项目.面积,视图_用户_物业项目.人数,视图_用户_物业项目.时间,视图_用户_物业项目.余额,视图_用户_物业项目.物业名称,视图_用户_物业项目.收费周期,视图_用户_物业项目.单价,视图_用户_物业项目.乘面积,视图_用户_物业项目.乘人数,视图_用户_物业项目.开始时间,DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE()) as 数量 , DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE())*视图_用户_物业项目.单价 * 视图_用户_物业项目.面积 AS 应收金额
FROM 视图_用户_物业项目,system
WHERE 视图_用户_物业项目.收费周期='每年一次' and 视图_用户_物业项目.乘面积 <> 0 and 视图_用户_物业项目.乘人数 = 0
ORDER BY 地址, 用户名称
UNION SELECT 视图_用户_物业项目.地址,视图_用户_物业项目.用户名称,视图_用户_物业项目.编号,视图_用户_物业项目.用户_ID,视图_用户_物业项目.电话,视图_用户_物业项目.区名称,视图_用户_物业项目.楼名称,视图_用户_物业项目.面积,视图_用户_物业项目.人数,视图_用户_物业项目.时间,视图_用户_物业项目.余额,视图_用户_物业项目.物业名称,视图_用户_物业项目.收费周期,视图_用户_物业项目.单价,视图_用户_物业项目.乘面积,视图_用户_物业项目.乘人数,视图_用户_物业项目.开始时间, DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE()) as 数量 , DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE())*视图_用户_物业项目.单价 * 视图_用户_物业项目.人数 AS 应收金额
FROM 视图_用户_物业项目,system
WHERE 视图_用户_物业项目.收费周期='每年一次' and 视图_用户_物业项目.乘面积 = 0 and 视图_用户_物业项目.乘人数 <> 0
ORDER BY 地址, 用户名称
UNION SELECT 视图_用户_物业项目.地址,视图_用户_物业项目.用户名称,视图_用户_物业项目.编号,视图_用户_物业项目.用户_ID,视图_用户_物业项目.电话,视图_用户_物业项目.区名称,视图_用户_物业项目.楼名称,视图_用户_物业项目.面积,视图_用户_物业项目.人数,视图_用户_物业项目.时间,视图_用户_物业项目.余额,视图_用户_物业项目.物业名称,视图_用户_物业项目.收费周期,视图_用户_物业项目.单价,视图_用户_物业项目.乘面积,视图_用户_物业项目.乘人数,视图_用户_物业项目.开始时间, DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE()) as 数量 , DateDiff('yyyy',DateSerial(year(视图_用户_物业项目.开始时间) , month(视图_用户_物业项目.开始时间 ) - system.AMonth , day(视图_用户_物业项目.开始时间) - system.ADay),DATE())*视图_用户_物业项目.单价 * 视图_用户_物业项目.人数 * 视图_用户_物业项目.面积 AS 应收金额
FROM 视图_用户_物业项目,system
WHERE 视图_用户_物业项目.收费周期='每年一次' and 视图_用户_物业项目.乘面积 <> 0 and 视图_用户_物业项目.乘人数 <> 0
ORDER BY 地址, 用户名称;


作者;段利庆(Lee) QQ:14035344

一卡通水电暖专家
http://www.duanliqing.kudos.cc/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐