在SQL中获取字符串中的远程和逗号分隔项的计数

时间:2012-05-01 21:03:39

标签: sql string count sql-server-2008-r2

在SQL SERVER 2008 R2中,我需要获取字符串中包含的项目数,这些项目可以具有以下任何特征(由用户而不是系统控制):

  • 以逗号分隔的每个项目
  • 由第一个和最后一个项目用短划线分隔的顺序项目
  • 仅附加到破折号分隔范围中的第一项的非增量字符
  • 表示指定的非增量部分的多个字符
  • 以上
  • 的组合

以下所有内容都是可能的:

  • R1,R2,R3,R4
  • R1-R4
  • R1-4
  • CP10-CP12
  • R1,R15-R19,RN5

如果它们都以逗号分隔,我可以只计算逗号+1,但这实际上不如其他选项。

计算最后一个选项的方法应适用于所有选项。结果应为7

我的预期方法是:

  1. 将项目分开,不用短划线,但用逗号分隔=>得到一个计数
  2. 隔离破折号分隔的项目并删除非增量字符
  3. 从较大的数字中减去较小的数字并添加1
  4. 将该号码添加到总计数的第一个数字
  5. 即使从哪​​里开始我也完全被困住了。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用技巧来计算逗号分隔列表中逗号的数量:

select len(str) - len(replace(str, ',', '')

对于完整的解决方案,您需要做一些更复杂的事情。很久以前,我下载了一个名为split的函数,它接受一个分隔的字符串并返回组件,就像它是一个表一样。事实上,我似乎从这里选择了它。 。 。 T-SQL: Opposite to string concatenation - how to split string into multiple records

因此,我们的想法是拆分字符串,然后解析组件以进行计数。如果你没有连字符,则计为“1”。如果有连字符,则需要解析字符串以获得计数。

答案 1 :(得分:1)

这可以清理/优化,故意冗长,但应该让你开始。值得注意的是,最后一个IF内部的逻辑几乎与WHILE的逻辑相同,并且获取左/右元素数值的块重复四次。

declare @input varchar(max)
set @input = 'R1,R15-R19,RN5-RN6'

select @input

declare @elements table
(
    Element varchar(10),
    [Count] int
)

declare @element varchar(10)
declare @index int
declare @count int
declare @left varchar(10)
declare @right varchar(10)
declare @position int

while (len(@input) > 0 and charindex(',', @input) > 0)
begin
    set @element = substring(@input, 0, charindex(',', @input))
    if (charindex('-', @element) > 0)
    begin
        set @index = charindex('-', @element)
        set @left = left(@element, @index - 1)
        set @right = substring(@element, @index + 1, len(@element) - len(@left))

        set @position = 0
        while (isnumeric(substring(@left, @position, 1)) = 0)
        begin
            set @position = @position + 1
        end
        set @left = substring(@left, @position, len(@left))

        set @position = 0
        while (isnumeric(substring(@right, @position, 1)) = 0)
        begin
            set @position = @position + 1
        end
        set @right = substring(@right, @position, len(@right))

        set @count = cast(@right as int) - cast(@left as int) + 1
    end
    else
    begin
        set @count = 1
    end
    insert into @elements select @element, @count
    set @input = replace(@input, @element + ',', '')
end

if (len(@input) > 0)
begin
    set @element = @input
    if (charindex('-', @element) > 0)
    begin
        set @index = charindex('-', @element)
        set @left = left(@element, @index - 1)
        set @right = substring(@element, @index + 1, len(@element) - len(@left))

        set @position = 0
        while (isnumeric(substring(@left, @position, 1)) = 0)
        begin
            set @position = @position + 1
        end
        set @left = substring(@left, @position, len(@left))

        set @position = 0
        while (isnumeric(substring(@right, @position, 1)) = 0)
        begin
            set @position = @position + 1
        end
        set @right = substring(@right, @position, len(@right))

        set @count = cast(@right as int) - cast(@left as int) + 1
    end
    else
    begin
        set @count = 1
    end
    insert into @elements select @element, @count
end

select * from @elements
select sum([Count]) from @elements

输出以下结果:

R1,R15-R19,RN5-RN6

R1      1
R15-R19 5
RN5-RN6 2

8