您的位置:首页 > 产品设计 > UI/UE

SqlServer 2005 T-SQL Query 学习笔记(4)

2010-02-18 21:24 651 查看
作者他很喜欢建立数字辅助表(即是1-N的数字按顺序组成的表),关于如何建立这些辅助表,然后他给了一些例子,这些例子很有代表性。

比如,我要建立一个1,000,000行的数字表:

CREATETABLEdbo.Nums(nINTNOTNULLPRIMARYKEY);
DECLARE@maxASINT,@rcASINT;
SET@max=1000000;
SET@rc=1;

INSERTINTONumsVALUES(1);
WHILE@rc*2<=@max
BEGIN
INSERTINTOdbo.NumsSELECTn+@rcFROMdbo.Nums;
SET@rc=@rc*2;
END

INSERTINTOdbo.Nums
SELECTn+@rcFROMdbo.NumsWHEREn+@rc<=@max;


这种方式非常巧妙,它并不是一个一个的循环插入,而是一次插入很多行,{1},{2},{3,4},{5,6,7,8}。。。

为什么这样会快呢?

是因为它节省了跟比较其他可用解决方案和记录这些日志的时间。

然后,作者给了一个CTE的递归的解决方案:

DECLARE@nASBIGINT;
SET@n=1000000;

WITHNumsAS
(
SELECT1ASn
UNIONALL
SELECTn+1FROMNumsWHEREn<@n
)
SELECTnFROMNums
OPTION(MAXRECURSION0);--为了移除默认100的递归限制

有个更优的CTE的解决方案,就是先生成很多行,然后用ROW_NUMBER进行计算,再选择ROW_NUMBER这列的值就可以了。

DECLARE@nASBIGINT;
SET@n=1000000;

WITHBaseAS
(
SELECT1ASn
UNIONALL
SELECTn+1FROMBaseWHEREn<CEILING(SQRT(@n))
),
ExpandAS
(
SELECT1ASc
FROMBaseASB1,BaseASB2
),
NumsAS
(
SELECTROW_NUMBER()OVER(ORDERBYc)ASn
FROMExpand
)
SELECTnFROMNumsWHEREn<=@n
OPTION(MAXRECURSION0);
利用笛卡尔积进行不断的累加,达到了22n行。
最后,作者给出了一个函数,用于生成这样的数字表:

CREATEFUNCTIONdbo.fn_nums(@nASBIGINT)RETURNSTABLE
AS
RETURN
WITH
L0AS(SELECT1AScUNIONALLSELECT1),
L1AS(SELECT1AScFROML0ASA,L0ASB),
L2AS(SELECT1AScFROML1ASA,L1ASB),
L3AS(SELECT1AScFROML2ASA,L2ASB),
L4AS(SELECT1AScFROML3ASA,L3ASB),
L5AS(SELECT1AScFROML4ASA,L4ASB),
NumsAS(SELECTROW_NUMBER()OVER(ORDERBYc)ASnFROML5)
SELECTnFROMNumsWHEREn<=@n;
GO


Technorati标签:sql2005,t-sql,query
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: