[SQL]透過common table expressions (CTE)來產生某區間的連續序號

  • 3970
  • 0
  • SQL
  • 2014-08-25

SQL CTE (common table expressions) 除了讓我們很方便的以遞迴的方式來取出樹狀結構的資料,還可以產生區間的資料哦!
如連續數值、日期等,本篇介紹如何產生某區間的連續序號

今天發現系統中取序號的Store Procedure的Read很高,詳細看一下才發現,它為了Support取多筆序號,而使用一個數值Table去做Cross Join。

而在SQL 2005之後,有提供 CTE  除了可組出組織的資料外,也可以利用它來產生某個區間的序號。

以下說明原本使用數值Table的做法及使用CTE 的方式,如下,

方法1:利用Table DIGITAL(存放0~9) + CROSS JOIN 出各數值資料

1.建立DIGITAL Table

CREATE TABLE [DIGITAL]
(
[DIGI] [tinyint] NOT NULL
)  
GO
insert into DIGITAL(DIGI) values(0);
insert into DIGITAL(DIGI) values(1);
insert into DIGITAL(DIGI) values(2);
insert into DIGITAL(DIGI) values(3);
insert into DIGITAL(DIGI) values(4);
insert into DIGITAL(DIGI) values(5);
insert into DIGITAL(DIGI) values(6);
insert into DIGITAL(DIGI) values(7);
insert into DIGITAL(DIGI) values(8);
insert into DIGITAL(DIGI) values(9);

 

2.多個 DIGITAL Table CROSS JOIN 出各數值資料

--目前的序號
DECLARE @CURRENT_SEQ INT
SET @CURRENT_SEQ = 1000;

--要取號的筆數
DECLARE @NUM_COUNT INT 
SET @NUM_COUNT = 12;

--最後的序號
DECLARE @AFTER_SEQ INT
SET @AFTER_SEQ = @CURRENT_SEQ + @NUM_COUNT;

--方法1:利用Table DIGITAL(存放0~9) + CROSS JOIN 出數值資料
SELECT @AFTER_SEQ - ((((A.DIGI*10+B.DIGI)*10+C.DIGI)*10+D.DIGI)*10+E.DIGI) AS SEQ_NO
FROM DIGITAL A 
CROSS JOIN DIGITAL B 
CROSS JOIN DIGITAL C
CROSS JOIN DIGITAL D
CROSS JOIN DIGITAL E 
WHERE (((A.DIGI*10+B.DIGI)*10+C.DIGI)*10+D.DIGI)*10+E.DIGI < @NUM_COUNT
ORDER BY (((A.DIGI*10+B.DIGI)*10+C.DIGI)*10+D.DIGI)*10+E.DIGI DESC;

所以,會產生1001~1012 12筆資料,如下,

image

 

方法2:使用 CTE 來產生各序號的資料,如下,

--目前的序號
DECLARE @CURRENT_SEQ INT
SET @CURRENT_SEQ = 1000;

--要取號的筆數
DECLARE @NUM_COUNT INT 
SET @NUM_COUNT = 12;

--最後的序號
DECLARE @AFTER_SEQ INT
SET @AFTER_SEQ = @CURRENT_SEQ + @NUM_COUNT;

;WITH SEQ_RESULT 
AS(
	SELECT @AFTER_SEQ AS SEQ_NO, @NUM_COUNT AS NUM_CNT
		UNION ALL
		SELECT Y.SEQ_NO - 1, Y.NUM_CNT -1
		FROM SEQ_RESULT Y
		WHERE Y.NUM_CNT > 1
)
SELECT SEQ_NO 
FROM SEQ_RESULT 
ORDER BY SEQ_NO;

同樣的,也會產生1001~1012 12筆資料,如下,

image

 

但2個的成本卻是差很多的哦! 如下,

image

image

 

除了數值外,日期也是可以的哦! 詳細請參考 Using common table expressions (CTE) to generate sequences !

當遞迴太多次(@NUM_COUNT = 102)時,會發生「The statement terminated. The maximum recursion 100 has been exhausted before statement completion.」(感謝Jei的提醒)!

所以如果要取的流水號很多的話,可設定 OPTION (MAXRECURSION 0) 不去限制次數(預設是100),或是加大那個值(0~32767)!

 

參考資料

Using common table expressions (CTE) to generate sequences

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^