从原始数据创建n个新行,例如(1000 .... 1000 + n)

时间:2017-12-23 13:34:57

标签: sql-server excel tsql ssis etl

我需要从Excel工作簿中读取数据,其中数据以这种方式存储:

Company       Accounts
Company1      (#3000...#3999)
Company2      (#4000..4019)+(#4021..4024)

使用SSIS中的OLE DB目标的预期输出将是:

Company       Accounts
Company1      3000
Company1      3001
Company1      3002
   .           .
   .           .
   .           .
Company1      3999
Company2      4000
Company2      4001
   .           .
   .           .
   .           .
Company2      4019
Company2      4021
   .           .
   .           .
Company2      4024

这让我感到困惑,我不知道如何开始处理这个问题。

有人对此有任何见解吗?

4 个答案:

答案 0 :(得分:3)

首先,您必须将数据插入某个临时表。 Here are several ways。然后运行此查询:

with cte as (
select 
    company, replace(replace(replace(accounts,'(',''),')',''),'+','')+'#' accounts 
from 
    (values ('company 1','#3000#3999'),('company 2','(#4000#4019)+(#4021#4024)')) data(company, accounts)
)
, rcte as (
    select 
        company, stuff(accounts, ind1, ind2 - ind1, '') acc, substring(accounts, ind1 + 1, ind2 - ind1 - 1) accounts
    from 
        cte
        cross apply (select charindex('#', accounts) ind1) ca
        cross apply (select charindex('#', accounts, ind1 + 1) ind2) cb
    union all
    select
        company, stuff(acc, ind1, ind2 - ind1, ''), substring(acc, ind1 + 1, ind2 - ind1 - 1)
    from
        rcte
        cross apply (select charindex('#', acc) ind1) ca
        cross apply (select charindex('#', acc, ind1 + 1) ind2) cb
    where
        len(acc)>1
)

select company, accounts from rcte
order by company, accounts

option (maxrecursion 0)

答案 1 :(得分:3)

您可以添加脚本组件来实现此目的:

  1. 添加脚本组件
  2. 使输出缓冲区与输入异步。
  3. 对于每一行拆分,从“帐户”列中检索“最小值”和“最大值”。
  4. 然后使用For循环遍历检索到的最小值和最大值之间的值。
  5. 在循环中创建输出行

答案 2 :(得分:1)

假设工作表中有2个单元格,我发生的一般逻辑是将第二个单元格(每行)爆炸两次。第一遍使用+作为分隔符拆分字符串,并为每个公司返回一行或多行。使用..作为分隔符重复该逻辑,但每行返回2列。有了它,你可以循环或使用数字表来生成desierd集。如何最好地在ssis中这样做是一个我无法回答的问题,因为这不是一个经验领域。数字表方法相对简单和常见。

答案 3 :(得分:1)

首先,您需要一个分割字符串功能,或者根据您的数据,您需要一个自定义分割功能。 我的示例使用此dbo.DelimitedSplit8K

但正如我在分析excel数据后所说,我可能会创建一个自定义TVF。

其次,您必须拥有数字表,您可以创建自己的逻辑之一。 这是一次创造和人口

CREATE TABLE tblnumber (number INT PRIMARY KEY)

INSERT INTO tblnumber
SELECT ROW_NUMBER() OVER (
        ORDER BY a.number
        )
FROM master..spt_values a
    ,master..spt_values b

这只是一个基于您当前数据集的概念。

您需要将所有Excel数据拉入临时表。

create table #staging(Company varchar(50),Accounts varchar(50))
insert into #staging values 
('Company1',   '#3000...#3999')
,('Company2','#4000..4019)+(#4021..4024')

然后,

;with CTE as
(
select Company
,min(ca.Item) MinAcoount,max(ca.Item) MaxAcoount
from 
(
select Company
,replace(replace(replace(replace(Accounts,'#','') ,')',''),'(',''),'+','.')Accounts
from #staging
)tbl
cross apply(Select * from dbo.DelimitedSplit8K(Accounts,'.'))ca
where ca.Item<>''
group by Company
)
select c.Company,number as Account from tblnumber n
inner join cte c on n.number>=MinAcoount and n.number<=MaxAcoount

因为我正在使用CTE。这只是为了理解。 帐户的清洁工作供您理解。