------------更新:201501071730------------

评论中又有一位【笑东风】兄给出改善建议,在此先感谢他。原理是借助行数较多的一个系统视图sys.all_columns与自身做cross join,以得到大量现成行数,详情请见回复。在我的原文中我也提到考虑过这种借助现有系统对象得到行的方法,但我想当然认为这样会导致访问基础表,性能不会好,所以试都没试就pass了,但事实证明我错了,他的法子经测性能比倍增法好太多,再次自我教训,实践才是硬道理!!!再次感谢【笑东风】兄。最终实现如下:

/*----------------------
函数:生成行 0.01
Author:AhDung
Update:201412310925
----------------------*/
CREATE FUNCTION dbo.FMakeRows(@num INT)
RETURNS TABLE
RETURN (
SELECT TOP (CASE WHEN @num IS NULL OR @num<0 THEN 0 ELSE @num END) ROW_NUMBER() OVER(ORDER BY a.object_id) AS 'RowNo'
FROM sys.all_columns a CROSS JOIN sys.all_columns b
)

------------更新:201501061241------------

评论中有朋友提到不如用with,我理解他说的是CTE递归,在此先感谢一下这位【空紫竹】兄提出建议。遂试了下用CTE实现,代码如下:

CREATE FUNCTION dbo.FMakeRows2(@num INT)
RETURNS TABLE
RETURN (
WITH cte AS (
SELECT 1 AS 'RowNo',1 AS 'Lv'
UNION ALL
SELECT RowNo+Lv,Lv*2 FROM cte WHERE RowNo+Lv<=@num
UNION ALL
SELECT RowNo+Lv*2,Lv*2 FROM cte WHERE RowNo+Lv*2<=@num
)
SELECT RowNo FROM cte
)

功能一样,原理是递归倍增,语句变少了,但性能比不上原文的方法,16384行上述方法要400ms左右,与逐行法差不多,而原文方法只要140ms,所以算不上好方法,权当学习一下CTE递归知识。如果我的实现有问题,还望路过大侠指点,谢谢。

------------原文:201412311300------------

作用:传入整数x,返回一张x行的表,只有一列RowNo,存储各行序号。

对于这个需求,我先是找有没有现成的函数或过程,结果是没找到,如果路过的朋友知道,还望告知,谢谢。

使用示例:

至于该函数具体可以应用到哪些场景,只可意会,需要的人自然觉得有用,觉得没用的说明不需要。上代码:

/*----------------------
函数:生成行 0.01
Author:AhDung
Update:201412310925
----------------------*/
ALTER FUNCTION dbo.FMakeRows(@num INT)
RETURNS @t TABLE (RowNo INT)
BEGIN IF @num IS NULL OR @num <= 0 RETURN INSERT @t VALUES(1) DECLARE @no INT = 1
WHILE @no*2 <= @num
BEGIN
INSERT @t SELECT RowNo+@no FROM @t
SET @no *= 2
END INSERT @t SELECT TOP (@num-@no) RowNo+@no FROM @t RETURN
END

实现说明:原理是先给@t塞一个初始行,完了循环insert自身,如此1变2、2变4、4变万物……,每一圈后@t的行数都是上一圈的2倍,直到行数x2大于所需行数(@num)前打住,即要把行数控制在小于等于@num的范围内,最后从现有行中抽取一部分补齐所差的行。例如,需要的行数是13,转到3圈后,@t有8行,就要打住了,因为再转就成16行了,8距离13所差的5行最后通过从@t中抽取top 5补齐。

实现该函数一开始想到的是根据@num循环,每圈插一行,需要几行就转几圈(逐行法),逻辑很简单,但这样做很老实,事实证明效率也不如上述方法(行数倍增),两种方法经测试到500行时就有明显差异了,到16384行时,倍增法在140ms左右,逐行法400ms左右,我想原因就是倍增法大大减少了循环圈数,16384行只需转14圈,而逐行法要老老实实转足16384圈呐~怕怕。

也想过从某个必定存在的系统表/视图获取行,如sys.objects,但这样会访问基础表,即使你根本不select它的任何字段,这样性能必然不如纯内存操作来的好,试都不用试。再说也不地道,作为函数,依赖越少越健壮。

路过朋友如有更好方法,还请不吝赐教,非常感谢。

【SQL】分享表值函数FMakeRows,用于生成行的更多相关文章

  1. SQL Server 表值函数

    表值函数还是很有意思的,我现在想实现一个功能.就是我查询出来的内容,我要对结果进行再次查询,也要输入参数,我想了想 1.存储过程  不能对执行后的结果进行再次查询,需要创建临时表,太麻烦 2.视图  ...

  2. 【SQL】sql版Split函数。用于拆分字符串为单列表格

    功能与.net版string.Split函数类似,只不过.net返回的是数组,这个返回的是一个单列表格,每个拆分出来的子串占一行.可选是否移除空格子串和重复项.市面上类似的函数不算少,但大多都是在循环 ...

  3. PCB MS SQL表值函数与CLR 表值函数 (例:字符串分割转表)

    将字符串分割为表表经常用到,这里 SQL表值函数与CLR  表值函数,两种实现方法例出来如下: SELECT * FROM FP_EMSDB_PUB.dbo.SqlSplit('/','1oz/1.5 ...

  4. T-SQL编程 —— 用户自定义函数(内嵌表值函数)

    内嵌表值函数 接上 <T-SQL编程 -- 用户自定义函数(标量函数)> http://www.cnblogs.com/viusuangio/p/6212072.html 内嵌表值函数可以 ...

  5. sql 表值函数与标量值函数

    写sql存储过程经常需要调用一些函数来使处理过程更加合理,也可以使函数复用性更强,不过在写sql函数的时候可能会发现,有些函数是在表值函数下写的有些是在标量值下写的,区别是表值函数只能返回一个表,标量 ...

  6. SQL Server中使用表值函数

    函数有很多限制,不能使用动态语句,不能使用临时表等等...细看一下,直接写语句就行了,不用动态语句 insert into @re select id,parid,@I from videoclass ...

  7. sql server 中的表值函数和标量值函数

      顾名思义:表值函数返回的是表,而标量值函数可以返回基类型 一.表值函数 用户定义表值函数返回 table 数据类型.对于内联表值函数,没有函数主体:表是单个 SELECT 语句的结果集. 以下示例 ...

  8. SQL Server进阶(六)表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数

    概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...

  9. PCB MS SQL 标量函数与表值函数(CLR) 实现文件与目录操作

    一.C#写SQL SERVER(CLR)实现文件操作 标量函数: 文件移动 ,复制,检测文件存在,写入新文件文本,读取文本,创建目录,删除目录,检测目录是否存在 /// <summary> ...

随机推荐

  1. 一天一小段js代码(no.1)

    10000个数字中缺少三个数,编程找出缺少的三个数字. 算法实现: /*生成10000个数中随机抽掉三个数后的数组*/ function supplyRandomArray(){ /*生成含有1000 ...

  2. python 模块加载

    python 模块加载 本文主要介绍python模块加载的过程. module的组成 所有的module都是由对象和对象之间的关系组成. type和object python中所有的东西都是对象,分为 ...

  3. [蓝牙] 5、Battery Service module

    Detailed Description This module implements the Battery Service with the Battery Level characteristi ...

  4. Windows进程通信 -- 共享内存(1)

    共享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 W ...

  5. Senparc.Weixin.MP SDK 微信公众平台开发教程(十五):消息加密

    前不久,微信的企业号使用了强制的消息加密方式,随后公众号也加入了可选的消息加密选项.目前企业号和公众号的加密方式是一致的(格式会有少许差别). 加密设置 进入公众号后台的“开发者中心”,我们可以看到U ...

  6. 这里有个坑---js日期格式yyyy-MM-dd与yyyy/MM/dd

    这里有个坑,---------每一个遇到的坑总结后都是一比财富. 我们写脚本的时候,一般定义一个日期格式会使用“2015-12-21”和“2015/12/21”两种数据格式,由于各取所需日期格式并没有 ...

  7. scp命令[转]

    scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...

  8. Atitit  如何让精灵控件运动

    Atitit  如何让精灵控件运动 ##让Sushi精灵动起来 上面的代码,我们创建了静态的sushiSprite,现在我们让它动起来.使它从屏幕顶部下落到屏幕底部.在addSushi方法中添加如下代 ...

  9. Index Seek和Index Scan的区别

    Index Seek是Sql Server执行查询语句时利用建立的索引进行查找,索引是B树结构,Sql Server先查找索引树的根节点,一级一级向下查找,在查找到相应叶子节点后,取出叶子节点的数据. ...

  10. codeforces B. Pasha and String(贪心)

    题意:给定一个长度为len的字符序列,然后是n个整数,对于每一个整数ai, 将字符序列区间为[ai,len-ai+1]进行反转.求出经过n次反转之后的序列! /* 思路1:将区间为偶数次的直接去掉!对 ...