由于您没有使用特定的 RDBMS 标记您的问题,因此我将不得不一般性地回答。
SQL 本身不提供您要查找的基本操作,这基本上是字符串拆分。这意味着您必须自己编写,或使用已在线发布的众多内容之一。
但是,由于数据中的范围,您使事情变得有些复杂。这意味着您的程序将如下所示:
- 将您的数据插入临时/内存表并以程序方式对其进行迭代(或者,使用游标来执行相同操作)
- 对于集合中的每条记录,提取非规范化字符串数据并将其拆分为
','
.
- 对于拆分数据中的每个元素,您必须将其拆分(对于
'-'
非范围元素,应该返回一个结果)。
- 如果您的第二次拆分 (on
'-'
) 产生一个结果,则它是一条记录,您可以将其插入最终目的地。如果它产生两个结果,那么它是一个范围,您必须从头到尾迭代(使用该拆分的元素 1 和 2)并将记录插入到最终目的地
评论后编辑
不幸的是,我对 PROC SQL 或 SAS 并不熟悉,因此我无法为此提供具体的解决方案。我可以在 SQL Server T-SQL 中发布以下内容,希望能帮助您入门。
declare @results table (idx int identity(1, 1), id varchar(5), data varchar(max))
declare @elements table (idx int identity(1, 1), element varchar(25))
declare @range table (idx int identity(1, 1), element varchar(25))
insert into @results (id, data)
select
your_id,
your_data
from your_source
declare @i int
declare @cnt int
declare @j int
declare @cnt2 int
declare @element varchar(25)
declare @first int
declare @second int
declare @start int
declare @end int
declare @id varchar(5)
declare @data varchar(max)
select @i = min(idx) - 1, @cnt = max(idx) from @results
while @i < @cnt
begin
select @i = @i + 1
select @id = id, @data = data from @results where idx = @i
delete @elements
insert into @elements (element)
select
element
from split(@data, ',')
select @j = min(idx) - 1, @cnt2 = max(idx) from @elements
while @j < @cnt2
begin
select @j = @j + 1
select @element = element from @elements where idx = @j
delete @range
insert into @range (element)
select
element
from split(@element, '-')
select @first = min(idx), @second = max(idx) from @range
if @first = @second --single element
insert into final_destination (id, value)
select
@id,
element
from @range
else if @second - @first = 1 -- two elements, as desired
begin
select @start = convert(int, element) - 1 from @range where idx = @first
select @end = convert(int, element) from @range where idx = @second
while @start < @end
begin
select @start = @start + 1
insert into final_destination (id, value)
values (@id, @start)
end
end
else -- error condition, bad input
end
end