如何在SQL Server中的特定列中查找以逗号分隔值重复的次数

时间:2018-02-08 12:17:55

标签: sql-server database

我有一个SQL Server表,如下所示,其中一列包含以逗号分隔的整数值。我想要的是获得特定数量的计数,如下面的预期结果

编辑: 我知道如何拆分逗号分隔值。但我的问题是我想要的输出。看到该计数列中的预期输出在所有表格中显示的是特定数字重复的时间。

例如:

Id     values
---------------
1      2,3
2      1,2,3
3      1,3
4      2,3

预期结果:

number  repeat count
--------------
1       2
2       3
3       4

任何人都可以帮我吗?如何编写查询以获得所需的输出?

提前致谢

2 个答案:

答案 0 :(得分:2)

看起来问题是如何聚合SPLIT函数的结果,而不是如何分割值。

SQL Server 2016提供内置的STRING_SPLIT函数来拆分分隔的字符串并将值作为表返回。在value字段中返回单个值。以下查询对value字段进行分组并返回计数:

declare @table table (id int, somevalues nvarchar(200))

insert into @table
values
(1,N'2,3'),
(2,N'1,2,3'),
(3,N'1,3'),
(4,N'2,3')

select value,count(* )
from @table 
    cross apply string_split(somevalues,',')
group by value

只要分割功能可用,就可以在先前版本中使用相同的查询。 Aaron Bertrand的文章(如this onefollow up)中描述了几乎所有可用的技术。最快的方法使用CLR和XML。

查询是相同的,唯一改变的是split函数返回的列的名称,例如:

select item,count(* )
from @table 
    cross apply dbo.SplitStrings_XML(somevalues,',')
group by item

在这两种情况下,结果都是:

value   (No column name)
1       2
2       3
3       4

答案 1 :(得分:0)

首先创建像这样的分割函数

    CREATE FUNCTION SplitString (
        @Input NVARCHAR(MAX)
        , @Character CHAR(1)
        )
    RETURNS @Output TABLE (Item NVARCHAR(1000))
    AS
    BEGIN
        DECLARE @StartIndex INT
            , @EndIndex INT

        SET @StartIndex = 1

        IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
        BEGIN
            SET @Input = @Input + @Character
        END

        WHILE CHARINDEX(@Character, @Input) > 0
        BEGIN
            SET @EndIndex = CHARINDEX(@Character, @Input)

            INSERT INTO @Output (Item)
            SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)

            SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
        END

        RETURN
    END
    GO

然后您可以按如下方式调整查询

    create table #temp(
    id int,
    test varchar(20)
    )
    insert into #temp (id,test) values (1,'1,2,3')


     SELECT t.id, count(sf.Item)
    FROM #temp AS t
    CROSS APPLY dbo.SplitString(t.test,',') AS sf
    group by t.id;

    drop table #temp