适用环境: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]的更多相关文章

  1. SQL SERVER 函数大全[转]

    SQL Server 函数大全 一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果.这些要求包括:执行计算与数学运算.转换数据.解析数值.组合值和聚合一个范围内的值等. 下 ...

  2. SQL Server数据库--》top关键字,order by排序,distinct去除重复记录,sql聚合函数,模糊查询,通配符,空值处理。。。。

    top关键字:写在select后面 字段的前面 比如你要显示查询的前5条记录,如下所示: select top 5 * from Student 一般情况下,top是和order by连用的 orde ...

  3. sql server 函数的自定义

    创建用户定义函数.这是一个已保存 Transact-SQL 或公共语言运行时 (CLR) 例程,该例程可返回一个值.用户定义函数不能用于执行修改数据库状态的操作.与系统函数一样,用户定义函数可从查询中 ...

  4. SQL常用函数总结

    SQL常用函数总结 这是我在项目开发中使用db2数据库写存储过程的时候经常用到的sql函数.希望对大家有所帮助: sql cast函数 (1).CAST()函数的参数是一个表达式,它包括用AS关键字分 ...

  5. 【转载】SQL SERVER 函数大全

    SQL Server 函数大全 一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果.这些要求包括:执行计算与数学运算.转换数据.解析数值.组合值和聚合一个范围内的值等. 下 ...

  6. C标准库-数值字符串转换与内存分配函数

    原文链接:http://www.orlion.ga/977/ 一.数值字符串转换函数 #include <stdlib.h> int atoi(const char *nptr); dou ...

  7. sql 判断 函数 存储过程是否存在的方法

    下面为您介绍sql下用了判断各种资源是否存在的代码,需要的朋友可以参考下,希望对您学习sql的函数及数据库能够有所帮助.库是否存在if exists(select * from master..sys ...

  8. DB2 SQL 日期函数

    DB2 SQL 日期函数1:CURRENT TIMESTAMP 函数:获取当前日期时间语法:CURRENT TIMESTAMP参数:当前日期时间返回值:当前日期时间 2:CURRENT DATE 函数 ...

  9. Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt

    PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...

随机推荐

  1. 用手机访问本地环境的利器ngrok

    我们在调试移动端页面,尤其是调试微信页面的时候,会遇到这样的情况,手机连着公司的wifi,开发环境(台式机)插着公司的网线,我们要用手机来访问开发环境下的页面.这个时候,如果网线和wifi是在同一个网 ...

  2. 虚拟化平台cloudstack(4)——几个异常

    cloudstack主机添加不成功 CloudStack正常启动,添加区域.提供点和群集都正常,但是添加主机时提示添加不成功. 先添加主机: 然后出现提示: 在网上找了一圈,基本上没什么回复,没办法, ...

  3. 项目管理师prince2

    项目管理师prince2 PRINCE2并不适合用于管理商业活动中的日常事物.商业日常事务通常是指组织机构日常运营中需要完成的那些工作.例如,公司it系统的维护,宾馆的房间整理,或者运营公司的客户呼叫 ...

  4. 缓存篇~第六回 Microsoft.Practices.EnterpriseLibrary.Caching实现基于方法签名的数据集缓存

    返回目录 这一讲中主要是说EnterpriseLibrary企业级架构里的caching组件,它主要实现了项目缓存功能,它支持四种持久化方式,内存,文件,数据库和自定义,对于持久化不是今天讨论的重要, ...

  5. Android开发学习之路-下拉刷新以及GridView的使用

    GridView是类似于ListView的控件,只是GridView可以使用多个列来呈现内容,而ListView是以行为单位,所以用法上是差不多的. 主布局文件,因为要做下拉刷新,所以加了一个Prog ...

  6. 复杂 XML 的 序列化 反序列化

    已知.xml(再此命名default.xml)文件,请将其反序列化到一个实例对象. <?xml version="1.0" encoding="utf-8" ...

  7. python中常用的函数与库一

    1, collections.deque 在python里如果我们用列表作为队列使用也是可以的,只是当从队尾删除或者增加元素的时候是很快的,但是从队首删除或者增加元素则要慢得多,这是因为在队首进行操作 ...

  8. java8--stream

    *:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...

  9. [OpenCV] Samples 07: create_mask

    鼠标画线,圈地,构造相关mask图片(黑白). 支持鼠标左键右键中间键点击事件. /* * create_mask.cpp * * Author: * Siddharth Kherada <si ...

  10. 在<a></a>标签中调用javascript脚本

    有时候,我们点击了<a></a>标签(除了跳转到指定链接外)想要它调用某个方法,及调用javascript脚本,该如何做: 方法1:<a href="javas ...