我有一些数据存储在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
如何使用查询获取所需数据?
答案 0 :(得分:3)
您需要拆分数据,然后转动数字列,然后对所有行应用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。这就是,
被</a><a>
取代的原因。
在构建有效的XMl之后,我们使用nodes()
来获取所有数字。结果看起来像(我们还使用ROW_NUMBER
函数创建一个列ID,以便知道哪个列在哪里):
现在,我们需要执行PIVOT
,正如您所说,我们拥有CSV的静态长度,我们需要PIVOT
超过12列。结果是这样的:
拥有此数据后,我们只需执行SUM
,但我们使用OVER()
来获取所有行的总和。然后使用CONCAT
,只需构建最终字符串。
答案 1 :(得分:2)
您可以使用以下
步骤说明
示例设置
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
希望这会对你有所帮助