使用拥有规则的多个分隔符(和 - )在sql中拆分数据

时间:2014-03-18 10:24:25

标签: sql sql-server tsql split numbers

我有这样的数据1,2,3,4-8,10,11

我想用这两条规则将数据拆分成行:

  1. ,只会将数据拆分为行。 Ex 1,2,3成为:

    1
    2
    3
    
  2. -将拆分为序列号。 Ex 4-8成为:

    4
    5
    6
    7
    8 
    
  3. SQL查询如何做到这一点?请回答并保持简单。

4 个答案:

答案 0 :(得分:2)

只要您的间隔小于2048(请告知我这些数字是否会更高),这将有效,并且@data会遵循您当前的语法:

declare @data varchar(50) = '1,2,3,4-8,10,11'

;with x as
(
     SELECT t.c.value('.', 'VARCHAR(2000)') subrow
     FROM (
         SELECT x = CAST('<t>' + 
               REPLACE(@data, ',', '</t><t>') + '</t>' AS XML)
     ) a
     CROSS APPLY x.nodes('/t') t(c)
), y as
(
SELECT 
CAST(coalesce(PARSENAME(REPLACE(subrow, '-', '.'), 2),
              PARSENAME(REPLACE(subrow, '-', '.'), 1)) as int) f,
CAST(PARSENAME(REPLACE(subrow, '-', '.'), 1) as int) t from x
)
select z.number from y
cross apply 
(select y.f + number number
from master..spt_values
where number <= y.t - y.f and type = 'p'
) z

结果:

1
2
3
4
5
6
7
8
10
11

答案 1 :(得分:1)

CREATE FUNCTION dbo.MultipleDelemiterSplit
(
   @List       NVARCHAR(MAX),
   @Delemiter1 Varchar(100),
   @Delemiter2 Varchar(100)
)
RETURNS  TABLE
AS

   RETURN
   ( 
      SELECT Item = FirstSet.cnt.value('(./text())[1]', 'nvarchar(4000)')
      FROM
      (
        SELECT x = CONVERT(XML, '<cnt>'
          + REPLACE(REPLACE(@List, ISNULL(@Delemiter1,''), '</cnt><cnt>') , ISNULL(@Delemiter2,''), '</cnt><cnt>')
          + '</cnt>').query('.')
      ) AS a CROSS APPLY x.nodes('cnt') AS FirstSet(cnt)
   );

GO 

Select * From dbo.MultipleDelemiterSplit ('10:0,11:1,12:3,13:4,15:5,16:6',',',':')

答案 2 :(得分:0)

对于问题的第一部分,您可以使用递归CTE:

select '1,2,3,4-8,10,11' as value into #testtab

with tst(DelimValue,Value) as
(
    select cast(LEFT(value,charindex(',',value+',')-1) as varchar(50)),stuff(value,1,charindex(',',value+','),'') 
    from #testtab
     union all
    select cast(LEFT(value,charindex(',',value+',')-1) as varchar(50)),stuff(value,1,charindex(',',value+','),'')
    from tst
    where value > ''
)
select DelimValue 
from tst

这会给你结果:

1
2
3
4-8
10
11

为了给予应有的信用,我从这里学到了这一点:Turning a Comma Separated string into individual rows

现在对于范围,我想你可以编写一个循环的过程,它将在破折号之前找到第一个整数作为开始,第二个整数作为结束,然后插入/返回该范围的行。虽然我认为必须有一种更聪明的方法来做到这一点。

答案 3 :(得分:0)

我刚为两个分隔符创建了一个示例,需要为泛型

做一些事情
CREATE FUNCTION dbo.SplitStrings
(
   @List       NVARCHAR(MAX),
   @Separator1 Varchar(100),
   @Separator2 Varchar(100)
)
RETURNS  TABLE 
AS

   RETURN 
   (  
      SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
      FROM 
      ( 
        SELECT x = CONVERT(XML, '<i>' 
          + REPLACE(REPLACE(@List, ISNULL(@Separator1,''), '</i><i>') , ISNULL(@Separator2,''), '</i><i>') 
          + '</i>').query('.')
      ) AS a CROSS APPLY x.nodes('i') AS y(i)
   );

GO  

Select * From dbo.SplitStrings ('1,2,3,4 5,6,7',',','-')

如果不需要第二个分隔符,则传递null或为空