2012-04-18 55 views
4

擁有一個像這樣的表:轉換範圍爲序列,而無需使用功能

FromKey | ToKey | Value 
------------------------ 
1  | 4 | AAA 
5  | 6 | BBB 

什麼是最有效的方式,得到以下結果?

Key | Value 
----------------- 
1 | AAA 
2 | AAA 
3 | AAA 
4 | AAA 
5 | BBB 
6 | BBB 

我知道如何使用表函數和CROSS APPLY來做到這點,但是這種方法對於大表格來說很慢。我想知道是否有更快的解決方案。

回答

4

這裏有一種方法去嘗試(完整的例子,可運行不變化):

-- Dummy data 
DECLARE @Data TABLE (FromKey INTEGER, ToKey INTEGER, Value VARCHAR(10)) 
INSERT @Data VALUES (1,4,'AAA'),(5,6,'BBB') 

-- table of numbers, 1-100 for demo purposes 
DECLARE @Numbers TABLE (Num INTEGER PRIMARY KEY) 
INSERT @Numbers 
SELECT TOP 100 ROW_NUMBER() OVER (ORDER BY object_id) 
FROM sys.objects 

SELECT n.Num, d.Value 
FROM @Data d 
    JOIN @Numbers n ON d.FromKey <= n.Num AND d.ToKey >= n.Num 

我會做什麼,是在數據庫中創建一個物理「數字」表,從1號填充到n,其中n是足夠大的數量以滿足您的需求。這將是一個表/數據創建 - 但是,然後該表可以用於上述目的。

+0

唉唉,數字表,有什麼你*不能*做? :) – AakashM 2012-04-18 08:39:35

1

只要這將作爲FROMKEY和TOKEY之間的差值小於2047

declare @t table(FromKey int, ToKey int, Value varchar(3)) 
insert @t values(1,4, 'AAA'), (5,6, 'BBB') 

select t.ToKey - m.number [Key], t.Value 
from @t t 
join 
master..spt_values m ON type = 'P' AND number <= ToKey - FromKey 
order by 1 

這裏是一個遞歸解決方案:

declare @t table(FromKey int, ToKey int, Value varchar(3)) 
insert @t values(1,4, 'AAA'), (5,6, 'BBB') 

;with a as 
(
select FromKey [Key], ToKey, Value from @t 
union all 
select [Key] + 1, ToKey, Value from a 
where [Key] < ToKey 
) 
select [Key], Value from a 
order by 1 
1
declare @t table 
(
FromKey int, 
ToKey int, 
Value varchar(10) 
) 

insert into @t values(1,4,'AAA') 
insert into @t values(6,9,'BBB'); 
with tab as 
( 
select FromKey , ToKey, Value from @t 
union all 
select FromKey + 1, ToKey, Value 
from tab where FromKey < ToKey 
) 
select FromKey, Value from tab order by 1