将字符串表达式解析为列

时间:2015-04-15 00:23:21

标签: mysql sql sql-server sql-server-2008 stored-procedures

我有一个字符串,例如32,21C2L5N8C存储在一个字段中。现在我想将此字符串扩展为如下:

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,CCCCCCCCCCCCCCCCCCCCCLLNNNNNCCCCCCCC

获得上述字符串后,我想计算逗号,C,L和N的数量。

有人可以帮我这个吗?

2 个答案:

答案 0 :(得分:2)

您可以使用Pattern Splitter来完成此操作。这是一个取自Dwain Camp的article。使用的函数PatternSplitCM由Chris Morris创建。

CREATE FUNCTION [dbo].[PatternSplitCM]
(
       @List                VARCHAR(8000) = NULL
       ,@Pattern            VARCHAR(50)
) RETURNS TABLE WITH SCHEMABINDING 
AS 

RETURN
    WITH numbers AS (
    SELECT TOP(ISNULL(DATALENGTH(@List), 0))
        n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
    FROM
    (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n),
    (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
    (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
    (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n))

    SELECT
        ItemNumber = ROW_NUMBER() OVER(ORDER BY MIN(n)),
        Item = SUBSTRING(@List,MIN(n),1+MAX(n)-MIN(n)),
        [Matched]
    FROM (
        SELECT n, y.[Matched], Grouper = n - ROW_NUMBER() OVER(ORDER BY y.[Matched],n)
        FROM numbers
        CROSS APPLY (
            SELECT [Matched] = CASE WHEN SUBSTRING(@List,n,1) LIKE @Pattern THEN 1 ELSE 0 END
        ) y
    ) d
    GROUP BY [Matched], Grouper

使用上面的函数,您可能希望使用模式'[^0-9]'拆分字符串,这意味着不是数字。然后,您可以转动结果,以便相应的numbercharacter位于同一行。之后,使用REPLICATE生成字符串并在最后连接它们。

您的最终查询是:

DECLARE 
    @String     VARCHAR(8000),
    @Pattern    VARCHAR(50),
    @Result     VARCHAR(MAX)

SELECT 
    @String     = '32,21C2L5N8C',
    @Pattern    = '[^0-9]',
    @Result     = ''


;WITH Cte AS(
    SELECT  
        ID = (s.ItemNumber + 1)/ 2,
        Number = MAX(CASE WHEN s.ItemNumber % 2 = 1 THEN s.Item END),
        Character = MAX(CASE WHEN s.ItemNumber % 2 = 0 THEN s.Item END)
    FROM dbo.[PatternSplitCM](@String, @Pattern) s
    GROUP BY (s.ItemNumber + 1)/ 2
)
SELECT @Result = @Result + REPLICATE(Character, Number) FROM Cte ORDER BY ID

SELECT @Result

SQL Fiddle


以下是逐步说明:

首先,使用模式'[^0-9]'拆分给定的字符串。

SELECT * FROM dbo.[PatternSplitCM](@String, @Pattern) s

结果是:

ItemNumber           Item       Matched
-------------------- ---------- -----------
1                    32         0
2                    ,          1
3                    21         0
4                    C          1
5                    2          0
6                    L          1
7                    5          0
8                    N          1
9                    8          0
10                   C          1

其次,转动结果,使相应的数字和字符位于同一行:

SELECT  
    ID = (s.ItemNumber + 1)/ 2,
    Number = MAX(CASE WHEN s.ItemNumber % 2 = 1 THEN s.Item END),
    Character = MAX(CASE WHEN s.ItemNumber % 2 = 0 THEN s.Item END)
FROM dbo.[PatternSplitCM](@String, @Pattern) s
GROUP BY (s.ItemNumber + 1)/ 2

结果是:

ID     Number     Character
------ ---------- ----------
1      32         ,
2      21         C
3      2          L
4      5          N
5      8          C

最后,使用REPLICATE(Number, Character)生成每个字符串并将它们连接起来以获得最终结果:

SELECT @Result = @Result + REPLICATE(Character, Number) FROM Cte ORDER BY ID
SELECT @Result

结果是:

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,CCCCCCCCCCCCCCCCCCCCCLLNNNNNCCCCCCCC

答案 1 :(得分:2)

您可以提取数字无数字字符然后复制每个字符,在 SQL Server 中您可以使用patindexreplicate函数(解释在代码中):

--table variable for holding extracted numbers and none number characters
declare @t table(id int identity(1,1), num int, nonnum char(1))

declare @str1 varchar(50)='32,21C2L5N8C' -- your current given string
declare @int1 varchar(50)='' --for number
declare @str2 varchar(50)='' --for none numeric characters
declare @result varchar(max)=''

while len(@str1)>1 --for parsing the given string
begin
    while (Select PatIndex('%[0-9]%', @str1))=1 --extract number
    begin 
        set @int1=@int1+substring(@str1,1,1)
        set @str1=substring(@str1,2,len(@str1)-1)
    end
    set @str2=substring(@str1,1,1) --extract none numeric character
    set @str1=substring(@str1,2,len(@str1)-1)
    insert into @t(num,nonnum)values (@int1,@str2)
    set @int1=''
    set @str2=''
end

select @result=@result+replicate(nonnum,num) from @t
select @result

<强>输出:

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,CCCCCCCCCCCCCCCCCCCCCLLNNNNNCCCCCCCC

编辑1:如果您在给定字符串中有前面没有数字的字符,并且您希望在上面的代码中添加额外的while循环后打印它:

--table variable for holding extracted numbers and none number characters
declare @t table(id int identity(1,1), num int, nonnum char(1))

declare @str1 varchar(50)='32,21C2L5NC' -- your current given string
declare @int1 varchar(50)='' --for number
declare @str2 varchar(50)='' --for none numeric characters
declare @result varchar(max)=''

while len(@str1)>1 --for parsing the given string
begin
    while (Select PatIndex('%[0-9]%', @str1))=1 --extract number
    begin 
        set @int1=@int1+substring(@str1,1,1)
        set @str1=substring(@str1,2,len(@str1)-1)
    end
    set @str2=substring(@str1,1,1) --extract none numeric character
    set @str1=substring(@str1,2,len(@str1)-1)
    insert into @t(num,nonnum)values (@int1,@str2)
    set @int1=''
    set @str2=''
    while (isnumeric(substring(@str1,1,1))=0 and len(@str1)>=1)
    begin
        set @str2=substring(@str1,1,1) --extract none numeric character
        set @str1=substring(@str1,2,len(@str1)-1)
        insert into @t(num,nonnum)values (1,@str2)
        set @int1=''
        set @str2=''
    end
end
select @result=@result+replicate(nonnum,num) from @t
select @result

输出:

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,CCCCCCCCCCCCCCCCCCCCCLLNNNNNC

编辑2:如果你想要每个字符的重复次数,只需查询上面代码中的@t表变量,我的意思是在上面的查询结尾处说:

select nonnum [char],num [repeat] from @t

输出:

char    repeat
,       32
C       21
L       2
N       5
C       1