【SQL】分享表值函数FMakeRows,用来生成行

【SQL】分享表值函数FMakeRows,用于生成行

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

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

使用示例:

【SQL】分享表值函数FMakeRows,用来生成行

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

/*----------------------
函数:生成行 0.01
Author:AhDung
Update:201412310925
----------------------*/
CREATE 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 = 0
WHILE POWER(2,@no+1)<=@num
BEGIN
INSERT @t SELECT RowNo+POWER(2,@no) FROM @t
SET @no += 1
END

IF @num <> POWER(2,@no)
BEGIN
DECLARE @pow INT = POWER(2,@no)
INSERT @t SELECT TOP (@num-@pow) RowNo+@pow FROM @t
END

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它的任何字段,这样性能必然不如纯内存操作来的好,试都不用试。再说也不地道,作为函数,依赖越少越健壮。

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