【问题标题】:Parse a String Expression into Columns将字符串表达式解析为列
【发布时间】:2015-06-20 18:51:57
【问题描述】:

我有一个字符串,例如 32,21C2L5N8C 存储在一个字段中。现在我想把这个字符串展开如下:

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

得到上面的字符串后,我想统计逗号、C、L、N的个数。

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 这是用于 Microsoft SQL 服务器还是 MySQL?请删除您不使用的系统的标签。
  • 目前两个系统都在运行。我的首要任务是在 SQL Server 中得到答案,但 MYSQL 也可以。

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


【解决方案1】:

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

--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 循环后打印它: p>

--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

【讨论】:

    【解决方案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
    

    【讨论】:

    • 嘿,太棒了。谢谢你。只有一个问题。如果我在字符前面没有数字,则此代码不起作用。我的错。我应该解释第二种情况。例如。 32,21C2L5NC C前面没有数字,所以默认取1。
    • 是不是所有字符的长度都是1
    • 例如32,21C2L5NC C 前面没有数字,所以 C 的默认值应为 1,因此输出字符串将为 ,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,CCCCCCCCCCCCCCCCCCCCCCLLNNNNNC
    • 我建议先格式化输入字符串以插入1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多