【问题标题】:Splitting multiple delimited values into multiple rows [duplicate]将多个分隔值拆分为多行[重复]
【发布时间】:2016-05-15 08:39:15
【问题描述】:

我一直在 StackOverflow 中寻找解决方案,但没有发现任何有用的东西。我遇到了一个问题,希望有人愿意帮助我。

我有这样的价值:

Create table DemoRecords
(
    CustID int identity (1,1),
    CustomerName varchar(50),
    CurrencyCode varchar(50),
    CurrentBalance varchar(50),
    DateValue varchar(50)
)
GO

INSERT INTO DemoRecords VALUES ('Mr. X', 'BDTýUSDýGBP','10500ý2500ý1050','20150101ý20150201ý20150301')

..我需要这样的输出:(请看下面的图片)

Picture

请不要建议我使用 CTE,因为该表中有超过 100 列。

【问题讨论】:

  • 您可以编写一个简单的循环来提取您关心的位并将它们放入数据库中。
  • 注意:即使在拆分值之后,您仍然需要将 DateValue 转换为实际的日期数据类型。
  • 你能解释一下吗,因为我完全糊涂了:(

标签: sql sql-server split delimited


【解决方案1】:

这是一个将字符串拆分为行的函数。下面是对您的 demorecords 表的查询,该表使用该函数来获取请求的结果。

create function dbo.split
(
    @delimited nvarchar(max),
    @delimiter nvarchar(5)
)
returns @rows table
(
    rownumber int not null identity(1,1),
    value nvarchar(max) not null
)
as
begin
    if @delimited is null return

    declare @delr_len int = len(@delimiter)
    declare @start_at int = 1
    declare @end_at int
    declare @deld_len int

    while 1=1
    begin
        set @end_at = charindex(@delimiter,@delimited,@start_at)
        set @deld_len = case @end_at when 0 then len(@delimited) else @end_at-@start_at end
        insert into @rows (value) values( substring(@delimited,@start_at,@deld_len) );
        if @end_at = 0 break;
        set @start_at = @end_at + @delr_len
    end

    return
end
go


select custid, customername, currencycode=currencycode.value, currentbalance=currentbalance.value, datevalue=datevalue.value
    from demorecords r
    cross apply (select rownumber, value from dbo.split(r.currencycode,'ý') ) currencycode
    cross apply (select rownumber, value from dbo.split(r.currentbalance,'ý') where rownumber = currencycode.rownumber ) currentbalance
    cross apply (select rownumber, value from dbo.split(r.datevalue,'ý') where rownumber = currencycode.rownumber ) datevalue

如果您有一列可能包含缺失值,请使用外部应用而不是内部应用来连接该列的函数结果。在以下示例中,DateValue 列缺少值 3 和值 4。

INSERT INTO DemoRecords VALUES ('Mr. X', 'BDTýUSDýGBPýEUR','10500ý2500ý1050ý','ý')

select custid, customername, currencycode=currencycode.value, currentbalance=currentbalance.value, datevalue=datevalue.value
from demorecords r
cross apply (select rownumber, value from dbo.split(r.currencycode,'ý') ) currencycode
cross apply (select rownumber, value from dbo.split(r.currentbalance,'ý') where rownumber = currencycode.rownumber ) currentbalance
outer apply (select rownumber, value from dbo.split(r.datevalue,'ý') where rownumber = currencycode.rownumber ) datevalue

或者,您可以清理输入以不丢失值。在上面的例子中,我希望 DateValue 是 'ýý' 而不是 'ý'。如果您的情况允许,您可能更喜欢查找和修复这些问题,而不是使用外连接。

【讨论】:

  • 非常感谢 Matt Dolfin :)
  • 亲爱的马特,我有一个场景。您能否在以下数据上运行您的函数,看看会发生什么。插入 DemoRecords 值('X 先生'、'BDTýUSDýGBPýEUR'、'10500ý2500ý1050ý'、'ý')。行号与其他列不匹配,因此无法获得预期的输出。
  • @Sajid Wasim,在您的最新方案中,DateValue 缺少第三个和第四个值。我希望它的值是“ýýý”,而不是“ý”。您可以只使用外部应用而不是内部应用来连接该列的函数结果。请参阅我的更新答案。或者,您可以清理输入以具有正确的列数。
  • 谢谢马特!我真的很感激。
  • 亲爱的马特,让我再次感谢你。我在我的 200K 数据文件上使用了您的解决方案,并且需要 8 个小时以上的时间来拆分 :(。您可以给我其他建议吗?
猜你喜欢
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2012-06-16
  • 1970-01-01
  • 2013-09-17
相关资源
最近更新 更多