国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

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

2024-07-21 02:48:06
字體:
來源:轉載
供稿:網友
【SQL】分享表值函數FMakeRows,用于生成行

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

評論中又有一位【笑東風】兄給出改善建議,在此先感謝他。原理是借助行數較多的一個系統視圖sys.all_columns與自身做cross join,以得到大量現成行數,詳情請見回復。在我的原文中我也提到考慮過這種借助現有系統對象得到行的方法,但我想當然認為這樣會導致訪問基礎表,性能不會好,所以試都沒試就pass了,但事實證明我錯了,他的法子經測性能比倍增法好太多,再次自我教訓,實踐才是硬道理!!!再次感謝【笑東風】兄。最終實現如下:

/*----------------------函數:生成行 0.01Author:AhDungUpdate:201412310925----------------------*/CREATE FUNCTION dbo.FMakeRows(@num INT)RETURNS TABLERETURN (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 TABLERETURN (WITH cte AS (SELECT 1 AS 'RowNo',1 AS 'Lv'UNION ALLSELECT RowNo+Lv,Lv*2 FROM cte WHERE RowNo+Lv<=@numUNION ALLSELECT 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.01Author:AhDungUpdate:201412310925----------------------*/ALTER FUNCTION dbo.FMakeRows(@num INT)RETURNS @t TABLE (RowNo INT)BEGINIF @num IS NULL OR @num <= 0 RETURNINSERT @t VALUES(1)DECLARE @no INT = 1WHILE @no*2 <= @numBEGININSERT @t SELECT RowNo+@no FROM @tSET @no *= 2ENDINSERT @t SELECT TOP (@num-@no) RowNo+@no FROM @tRETURNEND

實現說明:原理是先給@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它的任何字段,這樣性能必然不如純內存操作來的好,試都不用試。再說也不地道,作為函數,依賴越少越健壯。

路過朋友如有更好方法,還請不吝賜教,非常感謝。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 海安县| 抚宁县| 清涧县| 盐池县| 上杭县| 松桃| 抚顺市| 宾阳县| 沂南县| 滕州市| 尉犁县| 建德市| 鄂尔多斯市| 拉萨市| 荥经县| 新平| 长葛市| 河津市| 商城县| 米脂县| 吴川市| 福泉市| 西盟| 甘洛县| 三河市| 古交市| 江华| 邹城市| 荆门市| 阿瓦提县| 丽江市| 栾川县| 定边县| 历史| 达尔| 辽阳市| 新宾| 湘潭市| 乐至县| 颍上县| 黄龙县|