2017-08-02 51 views
3

我有一个表,其中有两列贷款no和counter_value。逗号分隔值在位的汇总

对每个贷款no都存有逗号分隔值列表。

declare @tbl table (loanno varchar(100) , counter_value varchar(200)) 

insert into @tbl 
values(‘pr0021’,‘1000,200,300,100,800,230’), 
(‘pr0021’,‘500,300,300,100,600,200’), 
(‘pr0021’,‘500,100,200,190,400,100’) 

我需要根据贷款数量和就地汇总(汇总)计数器值进行分组。 我需要如下的输出。

loanno counter_value 
pr0021 2000,600,800,390,1800,530 
+3

不是最大的数据库设计,但如果一致,我们可以使事情的工作。你在counter_values字段中有6个项目吗? – Eli

+0

是的,每个项目总会有6个值。 – hieko

+0

我同意@Eli,这是一个可怕的设计,因为它违反了1NF。由于您的设计,您必须在这里跳过很多圈。如果这是正确的标准化,这将是非常简单的。 –

回答

5

由于您对数据进行了非规范化处理,因此首先必须将其拆分为多列,然后执行聚合,然后重新创建分隔列。有很多分离器在那里,但这是我最喜欢的这种类型的东西。 http://www.sqlservercentral.com/articles/Tally+Table/72993/这个分离器的主要优点是它可以返回大多数其他分离器所不具备的每个值的位置。

利用这个分离器,你可以这样做。

with AggregateData as 
(
    select t.loanno 
     , s.ItemNumber 
     , TotalValue = sum(convert(int, s.Item)) 
    from @tbl t 
    cross apply dbo.DelimitedSplit8K(t.counter_value, ',') s 
    group by t.loanno 
     , s.ItemNumber 
) 

select ad.loanno 
    , STUFF((select ',' + convert(varchar(10), ad2.TotalValue) 
     from AggregateData ad2 
     where ad2.loanno = ad.loanno 
     order by ad2.ItemNumber 
     FOR XML PATH('')), 1, 1, '') 
from AggregateData ad 
group by ad.loanno 
2

肖恩的将是我的第一选择(+1)。

但是,如果有一个已知的(或固定的)数量的位置,考虑以下几点:

Select A.loanno 
     ,NewAggr = concat(sum(Pos1),',',sum(Pos2),',',sum(Pos3),',',sum(Pos4),',',sum(Pos5),',',sum(Pos6)) 
From @tbl A 
Cross Apply (
       Select Pos1 = n.value('/x[1]','int') 
         ,Pos2 = n.value('/x[2]','int') 
         ,Pos3 = n.value('/x[3]','int') 
         ,Pos4 = n.value('/x[4]','int') 
         ,Pos5 = n.value('/x[5]','int') 
         ,Pos6 = n.value('/x[6]','int') 
        From (Select cast('<x>' + replace(A.counter_value,',','</x><x>')+'</x>' as xml) as n) X 
      ) B 
Group By A.loanno 

返回

loanno NewAggr 
pr0021 2000,600,800,390,1800,530 

如果它与可视化帮助,CROSS应用生成

enter image description here