采用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查询:
作者;段利庆(Lee) QQ:14035344
一卡通水电暖专家
http://www.duanliqing.kudos.cc/
第一种:用户消耗的水电用量
在一个收费期段内,根据水表,电表计量的消耗量乘以单价,就是水电费。这种归类原因,主要是有计量消耗量数据的仪表。
第二种:用户期段内的服务费
例如:物业管理费,电梯费,卫生费等。这些费用计算的标准大多通过一个时间期段(如:每月、每天、每季度、每年等)还有用户住房的面积,住户人数等相关参数,来合理确定收费标准。
比如:卫生费由于住户的常住人口多,产生的生活垃圾等就多所以在收取卫生费的时候就要求将住户人数作为一个参数,这样收费对大多数用户来说更合理公平。
下面来谈下业务逻辑的数据库设计和实现。
基本信息表
查询视图
这里的设计内容比较多,大家都能设计出更好的。
我主要介绍下“视图_物业应交”这个视图的设计。
先提出点问题,算是引子
按照时间间隔收费,这个时间的间隔一般分为:“每月一次|每年一次|每天一次|每季度一次 ”四种,在实现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/
相关文章推荐
- SQL Server 2008 无法采用SQL认证模式登录(已解决)
- 利用pl/sql块解决复杂sql查询
- SQL统计数量,查询多列问题解决,(因为该列没有包含在聚合函数或 GROUP BY 子句中。)
- SQL反模式学习笔记18 减少SQL查询数据,避免使用一条SQL语句解决复杂问题
- 复杂 SQL 查询跑不动?DRDS 只读实例来解决!
- 利用子查询解决复杂sql问题
- C#连接SQL多条件复杂查询
- SQL order by ID desc/asc加一个排序的字段解决查询慢问题
- MS Sqlserver优化实战(解决CPU利用率高及查询操作速度慢)
- sql 复杂查询 多表查询 分页查询
- NULL对IN的查询的影响及解决示例.sql
- sql查询中子查询字段和 sql查询字段一样,的解决方法
- PL\SQL 打开时出现"动态执行表不可访问,本会话的自动统计被禁止"错误解决
- Hibernate通过SQL查询常量时只能返回第一个字符的解决方法
- 在C#中建立复杂的、灵活的SQL查询/命令
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装 【手记】走近科学之为什么明明实现了IEnumerable<T>的类型却不能调用LINQ扩展方法 【手记】手机网页弹出层后屏蔽底层的滑动响应 【手记】ASP.NET提示“未能创建类型”处理 【Web】一个非常简单的移动web消息框 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”
- sql语句查询得到的SqlDataSource填充gridview的行数统计
- SQL调优--记一次表统计信息未及时更新导致查询超级慢
- SQL统计查询一个表中的记录,然后减法运算
- 关于SQL中使用select sum查询结果为NULL的解决办法