在不使用函数的情况下将范围转换为序列

时间:2012-04-18 08:33:04

标签: sql-server tsql

有这样的表:

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来实现它,但对于大表来说这种方法很慢。我想知道是否有更快的解决方案。

3 个答案:

答案 0 :(得分: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是一个足够大的数字来满足您的需求。这将是一次性的表格/数据创建 - 但是表格可以用于上述目的。

答案 1 :(得分: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

答案 2 :(得分: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