Sql server sql中以逗号分隔的文本形式存储的求和矩阵列

Sql server sql中以逗号分隔的文本形式存储的求和矩阵列,sql-server,tsql,split,sql-server-2012,Sql Server,Tsql,Split,Sql Server 2012,我有一些数据存储在SQL Server数据库中,格式如下 Id Numbers ---------------------------- 1 1,0,0,1,0,2,1,0,0,1,0,1 2 1,0,0,2,0,0,1,0,0,1,0,1 3 1,0,0,1,1,0,1,0,0,1,0,1 4 1,0,0,1,0,5,1,0,0,1,0,1 所有数字数据都有固定的长度,但值不同 如何使用SQL查询按以下方式对数据求和 预期结果: Id Numbers ----------

我有一些数据存储在SQL Server数据库中,格式如下

Id  Numbers
----------------------------
1   1,0,0,1,0,2,1,0,0,1,0,1
2   1,0,0,2,0,0,1,0,0,1,0,1
3   1,0,0,1,1,0,1,0,0,1,0,1
4   1,0,0,1,0,5,1,0,0,1,0,1
所有数字数据都有固定的长度,但值不同

如何使用SQL查询按以下方式对数据求和

预期结果:

Id  Numbers
-----------------------------
1   4,0,0,5,1,7,4,0,0,4,0,4
2   4,0,0,5,1,7,4,0,0,4,0,4
3   4,0,0,5,1,7,4,0,0,4,0,4
4   4,0,0,5,1,7,4,0,0,4,0,4
稍后我想用求和替换原始数据

update m 
set m.Numbers = r.Numbers
from table matrices m
inner join (the result) r on r.Id =m.Id

如何使用查询获取所需数据?

您需要拆分数据,然后旋转数字列,然后对所有行应用SUM but

DECLARE @DataSource TABLE
(
    [Id] TINYINT
   ,[Numbers] VARCHAR(32)
);

INSERT INTO @DataSource ([Id], [Numbers])
VALUES (1, '1,0,0,1,0,2,1,0,0,1,0,1')
      ,(2, '1,0,0,2,0,0,1,0,0,1,0,1')
      ,(3, '1,0,0,1,1,0,1,0,0,1,0,1')
      ,(4, '1,0,0,1,0,5,1,0,0,1,0,1');

WITH DataSource AS
(
    SELECT [ID]
          ,CAST('<a>' + REPLACE([Numbers], ',', '</a><a>') + '</a>' AS XML) AS [Numbers]
    FROM @DataSource
), DataSourceNumbersSplit AS
(
    SELECT DS.[Id]
          ,T.c.value('.', 'INT') AS [number]
          ,ROW_NUMBER() OVER (PARTITION BY DS.[Id] ORDER BY T.c) AS [RowID]
    FROM DataSource DS
    CROSS APPLY DS.[Numbers].nodes('a') T(c)
)
SELECT [ID]
      ,CONCAT(SUM([1]) OVER (), ',', SUM([2]) OVER (), ',', SUM([3]) OVER (), ',', SUM([4]) OVER (), ',', SUM([5]) OVER (), ',', SUM([6]) OVER (), ',', SUM([7]) OVER (), ',', SUM([8]) OVER (), ',', SUM([9]) OVER (), ',', SUM([10]) OVER (), ',', SUM([11]) OVER (), ',', SUM([12]) OVER ()) AS [numbers]
FROM DataSourceNumbersSplit
PIVOT
(
    MAX([number]) FOR [RowID] IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) PVT;
第一个CTE仅用于为拆分准备[编号]。我们需要从给定的CSV构建XML。这就是为什么,被替换为

现在,我们需要执行透视,正如您所说的,我们有CSV的静态长度,我们需要透视12列。结果如下:


有了这些数据,我们只需要执行SUM,但我们使用OVER来获得所有行的总和。然后使用CONCAT,只需构建最后一个字符串。

您需要拆分数据,然后旋转数字列,然后对所有行应用SUM but

DECLARE @DataSource TABLE
(
    [Id] TINYINT
   ,[Numbers] VARCHAR(32)
);

INSERT INTO @DataSource ([Id], [Numbers])
VALUES (1, '1,0,0,1,0,2,1,0,0,1,0,1')
      ,(2, '1,0,0,2,0,0,1,0,0,1,0,1')
      ,(3, '1,0,0,1,1,0,1,0,0,1,0,1')
      ,(4, '1,0,0,1,0,5,1,0,0,1,0,1');

WITH DataSource AS
(
    SELECT [ID]
          ,CAST('<a>' + REPLACE([Numbers], ',', '</a><a>') + '</a>' AS XML) AS [Numbers]
    FROM @DataSource
), DataSourceNumbersSplit AS
(
    SELECT DS.[Id]
          ,T.c.value('.', 'INT') AS [number]
          ,ROW_NUMBER() OVER (PARTITION BY DS.[Id] ORDER BY T.c) AS [RowID]
    FROM DataSource DS
    CROSS APPLY DS.[Numbers].nodes('a') T(c)
)
SELECT [ID]
      ,CONCAT(SUM([1]) OVER (), ',', SUM([2]) OVER (), ',', SUM([3]) OVER (), ',', SUM([4]) OVER (), ',', SUM([5]) OVER (), ',', SUM([6]) OVER (), ',', SUM([7]) OVER (), ',', SUM([8]) OVER (), ',', SUM([9]) OVER (), ',', SUM([10]) OVER (), ',', SUM([11]) OVER (), ',', SUM([12]) OVER ()) AS [numbers]
FROM DataSourceNumbersSplit
PIVOT
(
    MAX([number]) FOR [RowID] IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) PVT;
第一个CTE仅用于为拆分准备[编号]。我们需要从给定的CSV构建XML。这就是为什么,被替换为

现在,我们需要执行透视,正如您所说的,我们有CSV的静态长度,我们需要透视12列。结果如下:


有了这些数据,我们只需要执行SUM,但我们使用OVER来获得所有行的总和。然后使用CONCAT,只需构建最后一个字符串。

您可以使用以下命令

步骤说明

把数字分成几行 对行求和 再把数字分组 示例设置

declare @data table(
          Id int not null identity(1,1),
          Numbers nvarchar(max) not null
)        
     insert into @data(Numbers)
     values('1,0,0,1,0,2,1,0,0,1,0,1'),
           ('1,0,0,2,0,0,1,0,0,1,0,1'),
           ('1,0,0,1,1,0,1,0,0,1,0,1'),
           ('1,0,0,1,0,5,1,0,0,1,0,1')
询问

    ;with Split as
    (
        select
            Id,1 as Number,left(Numbers,charindex(',',Numbers)-1) as Part
                ,right(Numbers,len(Numbers)-charindex(',',Numbers)) as Rest
            from @data
            where Numbers is not null and charindex(',',Numbers)>0
        union all
        select
            Id, Number +1,left(Rest,charindex(',',Rest)-1)
                ,right(Rest,len(Rest)-charindex(',',Rest))
            from Split
            where Rest is not null and charindex(',',Rest)>0
        union all
        select
            Id,Number+1,Rest,null
            from Split
            where Rest is not null and charindex(',',Rest)=0
    ),sumRows as(
        select Number ,sum(cast(Part as int)) as Total
        from Split
        group by Number
    ), groupValues as (
        select Id,stuff((
            select ',' + cast(r.Total as varchar)
            from sumRows r
            inner join Split s on s.Number = r.Number
            where (s.Id =d.Id ) 
            for xml path(''),type).value('(./text())[1]','varchar(max)')
          ,1,1,'') as Numbers
        from @data d
    )

    select * from groupValues
结果

Id  Numbers
1   4,0,0,5,1,7,4,0,0,4,0,4
2   4,0,0,5,1,7,4,0,0,4,0,4
3   4,0,0,5,1,7,4,0,0,4,0,4
4   4,0,0,5,1,7,4,0,0,4,0,4

希望这将帮助您

您可以使用以下工具

步骤说明

把数字分成几行 对行求和 再把数字分组 示例设置

declare @data table(
          Id int not null identity(1,1),
          Numbers nvarchar(max) not null
)        
     insert into @data(Numbers)
     values('1,0,0,1,0,2,1,0,0,1,0,1'),
           ('1,0,0,2,0,0,1,0,0,1,0,1'),
           ('1,0,0,1,1,0,1,0,0,1,0,1'),
           ('1,0,0,1,0,5,1,0,0,1,0,1')
询问

    ;with Split as
    (
        select
            Id,1 as Number,left(Numbers,charindex(',',Numbers)-1) as Part
                ,right(Numbers,len(Numbers)-charindex(',',Numbers)) as Rest
            from @data
            where Numbers is not null and charindex(',',Numbers)>0
        union all
        select
            Id, Number +1,left(Rest,charindex(',',Rest)-1)
                ,right(Rest,len(Rest)-charindex(',',Rest))
            from Split
            where Rest is not null and charindex(',',Rest)>0
        union all
        select
            Id,Number+1,Rest,null
            from Split
            where Rest is not null and charindex(',',Rest)=0
    ),sumRows as(
        select Number ,sum(cast(Part as int)) as Total
        from Split
        group by Number
    ), groupValues as (
        select Id,stuff((
            select ',' + cast(r.Total as varchar)
            from sumRows r
            inner join Split s on s.Number = r.Number
            where (s.Id =d.Id ) 
            for xml path(''),type).value('(./text())[1]','varchar(max)')
          ,1,1,'') as Numbers
        from @data d
    )

    select * from groupValues
结果

Id  Numbers
1   4,0,0,5,1,7,4,0,0,4,0,4
2   4,0,0,5,1,7,4,0,0,4,0,4
3   4,0,0,5,1,7,4,0,0,4,0,4
4   4,0,0,5,1,7,4,0,0,4,0,4
希望这对你有帮助