【SQL】分配函数一枚[AllotToTable]
适用环境:MSSQL 2005+。其中05需修改部分语句的写法才行,如:
--变量的声明和赋值需分开写
DECLARE @scale INT = 0 --需改为如下
DECLARE @scale INT; SET @scale = 0 --05不支持+=这样的复合运算符
SET @scale += 1 --需改为如下
SET @scale = @scale + 1
功能:
将一个数字(整数或有限小数)分配成指定份,每份一行,返回一个单列表格。
使用示例:

可见,这不是除法,而是为了尽可能公平的把数字分配完,该分配法有如下
特点:
- 不存在除不尽的情况
- 能保证所有份数之和与原数相等
- 结果精度与原数(被分配数)精度一致。3.470的精度视为0.01,所以它分成3份是1.16、1.16、1.15,而不是1.157、1.157、1.156
- 结果最多只会出现两种数值,大值与小值之差为原数精度的1个单位。即在原数精度范围内,各份之间的差值保证最小,以此做到尽可能公平的分配。如上例1.16与1.15相差0.01
- 若被分配数为NULL、或份数为NULL或0,返回0行
像这种分配法我估计在多种场景都有在用,它应该有个名堂的,只是我不知道,还请知道的猿友告知,谢谢。
函数源码:
/*--------------------
函数:分配0.01
Author:AhDung
Update:201504211157
--------------------*/
ALTER FUNCTION dbo.AllotToTable(@num DECIMAL(16,4), @div TINYINT)
RETURNS @t TABLE(Val DECIMAL(16,4))
BEGIN
IF @num IS NULL OR @div IS NULL OR @div=0 RETURN IF @div=1 --除数为1,直接返回1行
BEGIN
INSERT @t SELECT @num
RETURN
END IF @num=0 --被除数为0,直接返回@div行0
BEGIN
INSERT @t SELECT 0 FROM FMakeRows(@div)
RETURN
END /*得到@num的真实精度*/
DECLARE @scale INT=0, @numToInt DECIMAL(16,4)=@num
WHILE @numToInt % 1 <> 0
BEGIN
SET @numToInt *= 10
SET @scale += 1
END /*填充元素(舍弃过的)*/
DECLARE @roundDownItem DECIMAL(16,4)=ROUND(@num / @div, @scale, 1)
INSERT @t SELECT @roundDownItem FROM FMakeRows(@div) /*将余数均分到top n行。余数之所以不采用@num % @roundDownItem,是因为后者为1时就不对*/
DECLARE @mod DECIMAL(16,4) = @num - @roundDownItem*@@ROWCOUNT
IF @mod<>0
BEGIN
DECLARE @pow INT = POWER(10, @scale)
UPDATE TOP (CAST(ABS(@mod) * @pow AS INT)) @t
SET Val += SIGN(@mod)/@pow
END RETURN
END
函数中用到了一个叫做FMakeRows的自定义表值函数,有劳移步至这篇博文取用:http://www.cnblogs.com/ahdung/p/4195509.html,当然你可以小加改造,让它不依赖外部函数。
有尝试过用排名函数NTILE实现,借助它的组分配能力,但性能不理想,因为被分配数有多大,就得构造多大行数的表格,空间和时间都不值得。另请老鸟指点改善,谢谢。
-文毕-
【SQL】分配函数一枚[AllotToTable]的更多相关文章
- SQL SERVER 函数大全[转]
SQL Server 函数大全 一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果.这些要求包括:执行计算与数学运算.转换数据.解析数值.组合值和聚合一个范围内的值等. 下 ...
- SQL Server数据库--》top关键字,order by排序,distinct去除重复记录,sql聚合函数,模糊查询,通配符,空值处理。。。。
top关键字:写在select后面 字段的前面 比如你要显示查询的前5条记录,如下所示: select top 5 * from Student 一般情况下,top是和order by连用的 orde ...
- sql server 函数的自定义
创建用户定义函数.这是一个已保存 Transact-SQL 或公共语言运行时 (CLR) 例程,该例程可返回一个值.用户定义函数不能用于执行修改数据库状态的操作.与系统函数一样,用户定义函数可从查询中 ...
- SQL常用函数总结
SQL常用函数总结 这是我在项目开发中使用db2数据库写存储过程的时候经常用到的sql函数.希望对大家有所帮助: sql cast函数 (1).CAST()函数的参数是一个表达式,它包括用AS关键字分 ...
- 【转载】SQL SERVER 函数大全
SQL Server 函数大全 一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果.这些要求包括:执行计算与数学运算.转换数据.解析数值.组合值和聚合一个范围内的值等. 下 ...
- C标准库-数值字符串转换与内存分配函数
原文链接:http://www.orlion.ga/977/ 一.数值字符串转换函数 #include <stdlib.h> int atoi(const char *nptr); dou ...
- sql 判断 函数 存储过程是否存在的方法
下面为您介绍sql下用了判断各种资源是否存在的代码,需要的朋友可以参考下,希望对您学习sql的函数及数据库能够有所帮助.库是否存在if exists(select * from master..sys ...
- DB2 SQL 日期函数
DB2 SQL 日期函数1:CURRENT TIMESTAMP 函数:获取当前日期时间语法:CURRENT TIMESTAMP参数:当前日期时间返回值:当前日期时间 2:CURRENT DATE 函数 ...
- Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt
PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...
随机推荐
- 我YY的一个移动应用运营模式
尽管自己也还是刚刚毕业不久的前端新人,但网上也不乏一些案例告诉我们有志不在年高,很多优秀的同龄人已经有了不错的成就,所以在切页面写onclick之余也在进行一些思考,前端程序员的出路到底在哪里? 一. ...
- C#Light V0.08A 执行字符串中的C#
C#Lite第一批规划的功能已经全部完成 V0.08A 加入了var 表达式支持 完成了类型静态函数和静态成员的访问 之前已完成了非静态的 之所以还不进入beta是临时决定第一批就加入数组的功能. 项 ...
- Java中文编码小结
Java中文编码小结 1. 只有 字符到字节 或者 字节到字符 的转换才存在编码转码; 2. Java String 采用 UTF-16 编码方式存储所有字符.unicode体系采用唯一的码点表示唯一 ...
- CSS3动画:YouTube的红色激光进度条
本文只是讨论和实现了动画效果,并未将动画与页面实际下载关联,有朋友们问如何应用,可以使用现成的一些插件比如这个,这个,还有这个. 之前一篇文章<CSS3 动画一瞥>简单介绍了CSS3动画相 ...
- jq源码立即执行函数的undefined参数
函数参数是undefined,那这个undefined是个变量标识符还是值呢? <JS权威指南>函数一章讲过,未给函数形参传值的时候,该形参的值是undefined.所以形参undefin ...
- 去除NSString里面的空格
NSString *password = @"12 34"; [password stringByTrimmingCharactersInSet:[NSCharacterSet ...
- Java-继承 共3题
一.实现一个名为Person的类和它的子类Employee,Employee有两个子类Faculty和Staff.具体要求如下: (1)Person类中的属性有:姓名name(String类型),地址 ...
- EF架构~豁出去了,为了IOC,为了扩展,改变以前的IRepository接口
回到目录 使用了4年的IRepository数据仓储接口,今天要改变了,对于这个数据仓储操作接口,它提倡的是简洁,单纯,就是对数据上下文的操作,而直正的数据上下文本身我们却把它忽略了,在我的IRepo ...
- ServletConfig对象详解
在Servlet 的配置文件中,可以用一个或多个<init-param>标签为servlet配置一些初始化参数. 当servlet配置了初始化参数之后,web容器在创建servlet实例对 ...
- Leetcode 4 Median of Two Sorted Arrays 二分查找(二分答案+二分下标)
貌似是去年阿里巴巴c++的笔试题,没有什么创新直接照搬的... 题意就是找出两个排序数组的中间数,其实就是找出两个排序数组的第k个数. 二分答案,先二分出一个数,再用二分算出这个数在两个排序数组排序第 ...