SqlServer 2005 T-SQL Query 學(xué)習(xí)筆記(4)
更新時(shí)間:2010年02月19日 15:00:53 作者:
作者他很喜歡建立數(shù)字輔助表(即是1-N的數(shù)字按順序組成的表),關(guān)于如何建立這些輔助表,然后他給了一些例子,這些例子很有代表性。
比如,我要建立一個(gè)1,000,000行的數(shù)字表:
CREATE TABLE dbo.Nums(n INT NOT NULL PRIMARY KEY);
DECLARE @max AS INT, @rc AS INT;
SET @max = 1000000;
SET @rc = 1;
INSERT INTO Nums VALUES(1);
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO dbo.Nums SELECT n + @rc FROM dbo.Nums;
SET @rc = @rc * 2;
END
INSERT INTO dbo.Nums
SELECT n + @rc FROM dbo.Nums WHERE n + @rc <= @max;
這種方式非常巧妙,它并不是一個(gè)一個(gè)的循環(huán)插入,而是一次插入很多行,{1},{2},{3,4},{5,6,7,8}。。。
為什么這樣會(huì)快呢?
是因?yàn)樗?jié)省了跟比較其他可用解決方案進(jìn)行比較和記錄這些日志的時(shí)間。
然后,作者給了一個(gè)CTE的遞歸的解決方案:
DECLARE @n AS BIGINT;
SET @n = 1000000;
WITH Nums AS
(
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM Nums WHERE n < @n
)
SELECT n FROM Nums
OPTION(MAXRECURSION 0);--為了移除默認(rèn)100的遞歸限制
有個(gè)更優(yōu)的CTE的解決方案,就是先生成很多行,然后用ROW_NUMBER進(jìn)行計(jì)算,再選擇ROW_NUMBER這列的值就可以了。
DECLARE @n AS BIGINT;
SET @n = 1000000;
WITH Base AS
(
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM Base WHERE n < CEILING(SQRT(@n))
),
Expand AS
(
SELECT 1 AS c
FROM Base AS B1, Base AS B2
),
Nums AS
(
SELECT ROW_NUMBER() OVER(ORDER BY c) AS n
FROM Expand
)
SELECT n FROM Nums WHERE n <= @n
OPTION(MAXRECURSION 0);
利用笛卡爾積進(jìn)行不斷的累加,達(dá)到了22n行。
最后,作者給出了一個(gè)函數(shù),用于生成這樣的數(shù)字表:
CREATE FUNCTION dbo.fn_nums(@n AS BIGINT) RETURNS TABLE
AS
RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L5)
SELECT n FROM Nums WHERE n <= @n;
GO
CREATE TABLE dbo.Nums(n INT NOT NULL PRIMARY KEY);
DECLARE @max AS INT, @rc AS INT;
SET @max = 1000000;
SET @rc = 1;
INSERT INTO Nums VALUES(1);
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO dbo.Nums SELECT n + @rc FROM dbo.Nums;
SET @rc = @rc * 2;
END
INSERT INTO dbo.Nums
SELECT n + @rc FROM dbo.Nums WHERE n + @rc <= @max;
這種方式非常巧妙,它并不是一個(gè)一個(gè)的循環(huán)插入,而是一次插入很多行,{1},{2},{3,4},{5,6,7,8}。。。
為什么這樣會(huì)快呢?
是因?yàn)樗?jié)省了跟比較其他可用解決方案進(jìn)行比較和記錄這些日志的時(shí)間。
然后,作者給了一個(gè)CTE的遞歸的解決方案:
DECLARE @n AS BIGINT;
SET @n = 1000000;
WITH Nums AS
(
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM Nums WHERE n < @n
)
SELECT n FROM Nums
OPTION(MAXRECURSION 0);--為了移除默認(rèn)100的遞歸限制
有個(gè)更優(yōu)的CTE的解決方案,就是先生成很多行,然后用ROW_NUMBER進(jìn)行計(jì)算,再選擇ROW_NUMBER這列的值就可以了。
復(fù)制代碼 代碼如下:
DECLARE @n AS BIGINT;
SET @n = 1000000;
WITH Base AS
(
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM Base WHERE n < CEILING(SQRT(@n))
),
Expand AS
(
SELECT 1 AS c
FROM Base AS B1, Base AS B2
),
Nums AS
(
SELECT ROW_NUMBER() OVER(ORDER BY c) AS n
FROM Expand
)
SELECT n FROM Nums WHERE n <= @n
OPTION(MAXRECURSION 0);
利用笛卡爾積進(jìn)行不斷的累加,達(dá)到了22n行。
最后,作者給出了一個(gè)函數(shù),用于生成這樣的數(shù)字表:
復(fù)制代碼 代碼如下:
CREATE FUNCTION dbo.fn_nums(@n AS BIGINT) RETURNS TABLE
AS
RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L5)
SELECT n FROM Nums WHERE n <= @n;
GO
相關(guān)文章
sqlserver2005使用row_number() over分頁的實(shí)現(xiàn)方法
sqlserver2005使用row_number() over分頁的實(shí)現(xiàn)方法,需要的朋友可以參考下。2011-11-11
win2003 Server配置SQL Server 2005遠(yuǎn)程連接的方法
這篇文章主要介紹了win2003 Server配置SQL Server 2005遠(yuǎn)程連接的方法,需要的朋友可以參考下2015-01-01
sqlserver 通用存儲(chǔ)過程分頁代碼(附使用ROW_NUMBER()和不使用ROW_NUMBER()兩種情況性能分析
通用存儲(chǔ)過程分頁(使用ROW_NUMBER()和不使用ROW_NUMBER()兩種情況)性能分析2010-05-05
Win2008中安裝的MSSQL2005后無法訪問的解決方法
最近筆者一直在使用Win2008系統(tǒng),不過發(fā)現(xiàn)一個(gè)很奇怪的問題,那就是在該系統(tǒng)上安裝了SQL2005后,再在其他計(jì)算機(jī)訪問該主機(jī)顯示不能訪問2014-07-07
SQL Server 2005通用分頁存儲(chǔ)過程及多表聯(lián)接應(yīng)用
分頁存儲(chǔ)過程在好多文章中都有介紹過;本篇是不久前寫的一個(gè)分頁存儲(chǔ)過程,可應(yīng)用于SQL Server 2005上面,感興趣的朋友可以研究下,希望本文對(duì)你學(xué)習(xí)存儲(chǔ)過程有所幫助2013-01-01
解析SQL2005中如何使用CLR函數(shù)獲取行號(hào)
本篇文章是對(duì)SQL2005中如何使用CLR函數(shù)獲取行號(hào)的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
SQL server 2005將遠(yuǎn)程數(shù)據(jù)庫導(dǎo)入到本地的方法
這篇文章主要介紹了SQL server 2005將遠(yuǎn)程數(shù)據(jù)庫導(dǎo)入到本地的方法,需要的朋友可以參考下2015-01-01

