查询以选择以逗号分隔的数字范围

时间:2014-09-30 19:43:04

标签: sql sql-server

我需要一点帮助来编写一个查询来输出用逗号分隔的数字列表。我有一个有三列的表。第一列称为“低”,第二列称为“高”,第三列表示第1列和第2列之间的数字范围是连续范围还是奇数/偶数范围(1表示连续2表示奇数/偶数)。我想输出(并存储在不同表中的不同列中)每个相应的低/高范围用逗号分隔的数字范围。请参阅下面的示例(desired_result列是我想要查询的输出)

Low      High      oe_cons      desired_result
1        5         1            1,2,3,4,5
6        10        2            6,8,10
99       102       1            99,100,101,102
150      156       2            150,152,154,156
87       91        2            87,89,91

我的数据库是MS SQL Express 2012.非常感谢任何帮助。

由于

3 个答案:

答案 0 :(得分:0)

创建一个为您返回字符串的函数。



create function return_op(@low int, @high int, @oe_coin int)
returns varchar(1000)
 as
 begin
declare @a varchar(3000)

set @a = ''
select @a = coalesce(@a + ',', '') + cast(n as varchar(3)) from (select n from (
		SELECT TOP 1000 n = ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects 
		
		ORDER BY n)a
where n between @low and @high
and (n-@low)%@oe_coin = 0 )a

return substring(@a, 2, 1000)
end




然后变得相当简单



select low, high, oe_coin, return_op(low, high, oe_coin) from Table1




答案 1 :(得分:0)

这是另一种方法。这种方式不使用标量函数,它使用一个小技巧构建计数表,因此您不必读取单个基表而不是使用任何系统表。

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

go

create table #Something
(
    SomeKey int identity,
    Low int,
    High int,
    oe_cons int
)

insert #Something
select 1, 5 , 1 union all
select 6, 10, 2 union all
select 99, 102, 1 union all
select 150, 156, 2 union all
select 87, 91, 2;

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
--I actually have the above 4 ctes as a view in my system so I can reference it at any point
--it is the fastest way possible to generate 10k rows. There is not even a single read in 
--the execution plan for it. :)
, FilteredResults as
(
    select *
    from #Something s
    join cteTally t on t.N >= s.Low and t.N <= s.High
)

select SomeKey,
    STUFF((select ',' + cast(N as varchar(4))
    from FilteredResults fr2
    where fr2.SomeKey = fr.SomeKey
        and (fr2.N + fr2.Low) % fr2.oe_cons = 0
    order by N
    for xml path('')), 1, 1, '')
from FilteredResults fr
group by SomeKey
order by SomeKey

答案 2 :(得分:0)

ROW_NUMBER()为您提供一个数字序列。 TOP限制它。 ','+LTRIM(STR())将其设为文字。 FOR XML连接。 STUFF删除了主要逗号。

SELECT *
FROM MyTable a
CROSS APPLY (
    SELECT STUFF((
      SELECT TOP((a.High-a.Low)/a.oe_cons+1)
        ','+LTRIM(STR(a.Low+a.oe_cons*(ROW_NUMBER() OVER(ORDER BY (SELECT 1))-1)))
      FROM master.dbo.spt_values
      FOR XML PATH('')
    ),1,1,'')
) b(desired_result)