【问题标题】:Sum matrix columns stored as comma separated text in sql求和矩阵列存储为 sql 中的逗号分隔文本
【发布时间】:2017-11-19 10:51:09
【问题描述】:

我有一些数据以下列格式存储在 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

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

【问题讨论】:

    标签: sql-server tsql split sql-server-2012


    【解决方案1】:

    您需要拆分数据,然后旋转数字列,然后应用SUM,但适用于所有行。

    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 仅用于准备我们的 [Numbers] 进行拆分。我们需要从给定的 CSV 构建一个 XML。这就是,&lt;/a&gt;&lt;a&gt; 取代的原因。

    构建有效的 XMl 后,我们使用 nodes() 获取所有数字。结果看起来像(我们还使用ROW_NUMBER 函数创建了一个列ID,以便知道哪一列在哪里):

    现在,我们需要执行PIVOT,正如你所说,我们需要PIVOT 超过 12 列的 CSV 的静态长度。结果是这样的:

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

    【讨论】:

      【解决方案2】:

      你可以使用下面的

      步骤说明

      1. 将数字分成几行
      2. 对行求和
      3. 再次对数字进行分组

      示例设置

      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
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-18
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-19
        相关资源
        最近更新 更多