Разделение нескольких значений с разделителями на несколько строк [дубликаты]

Я искал решение в 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')

.. и мне нужен такой вывод: (Пожалуйста, взгляните на картинку, прикрепленную ниже)

введите здесь описание изображения Изображение

Пожалуйста, не предлагайте мне использовать CTE, потому что в этой таблице более 100 столбцов.


person Sajid Wasim    schedule 15.05.2016    source источник
comment
Вы можете написать простой цикл, чтобы извлечь нужные вам биты и поместить их в базу данных.   -  person Toby Allen    schedule 15.05.2016
comment
Примечание. Даже после того, как вы разделите значения, вам все равно нужно будет преобразовать DateValue в фактический тип данных даты.   -  person Zohar Peled    schedule 15.05.2016
comment
Не могли бы вы объяснить немного больше, потому что я полностью запутался :(   -  person Sajid Wasim    schedule 15.05.2016


Ответы (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 будет «ýýý», а не «ý». Если ваша ситуация позволяет, вы можете найти и исправить их, а не использовать внешнее соединение.

person matt.dolfin    schedule 15.05.2016
comment
Большое спасибо, Мэтт Долфин :) - person Sajid Wasim; 15.05.2016
comment
Дорогой Мэтт, у меня есть сценарий. Не могли бы вы запустить свою функцию для этих данных ниже и посмотреть, что произойдет. ВСТАВЬТЕ В ЗНАЧЕНИЯ DemoRecords ("Mr. X", "BDTýUSDýGBPýEUR", "10500ý2500ý1050ý", "ý"). номер строки не совпадает с другими столбцами, поэтому ожидаемый результат не получен. - person Sajid Wasim; 15.05.2016
comment
@Sajid Wasim, в вашем последнем сценарии DateValue отсутствуют третье и четвертое значения. Я ожидаю, что он будет иметь значение «ýýý», а не «ý». Вы можете просто использовать внешнее приложение вместо внутреннего, чтобы присоединиться к результату функции для этого столбца. Смотрите мой обновленный ответ. Или вы можете очистить свой ввод, чтобы иметь правильное количество столбцов. - person matt.dolfin; 15.05.2016
comment
Спасибо, Мэтт! Я действительно ценю. - person Sajid Wasim; 16.05.2016
comment
Дорогой Мэтт, позвольте еще раз поблагодарить вас. Я использовал ваше решение для моего файла данных объемом 200 КБ, и на его разделение ушло более 8 часов :(. Можете ли вы предложить мне что-нибудь еще? - person Sajid Wasim; 17.05.2016