Как я могу создать совокупную конкатенацию строк по строкам с упорядочением строки? - PullRequest
0 голосов
/ 02 июля 2019

Я хочу добавить в мою базу данных столбец, который выполняет построчную кумулятивную конкатенацию значений другого столбца для каждого идентификатора и упорядочивает результирующую строку по другой иерархии. Набор данных очень большой, и результат, который я разработал для меньших тестовых данных, не работает в более широком масштабе, поэтому мне нужна помощь в его редизайне.

На данный момент я написал запрос, используя комбинацию рекурсивного CTE для выполнения кумулятивной конкатенации (вывод шага 1 ниже), а затем немного неуклюжей функции (вывод шага 2 ниже), чтобы упорядочить строки в соответствии с отдельной иерархией который также удаляет значение «1». Они работают на небольшом подмножестве моих данных (n = 60), но когда я пытаюсь запустить большее подмножество (n = 500 000), таблица CTE запускается вечно (останавливается без завершения в 2 часа). Реальный набор данных будет иметь порядок сотен миллионов строк, поэтому решение не подходит для такого масштаба.

ID  Start_Date  End_Date    Seg step1       step2
1   01/04/1946  31/12/1990  1   1            1
1   01/01/1991  08/01/2007  4   4            4
1   09/01/2007  04/02/2007  1   1            1
1   05/02/2007  18/10/2017  4   14           4
1   01/04/2013  18/10/2017  8   148          48
1   11/11/2014  18/10/2017  7   1487         487
2   01/05/1931  31/12/1997  1   1            1
2   01/01/1998  20/01/2014  4   4            4
2   31/01/2011  20/01/2014  6   146          46
2   21/02/2013  20/01/2014  5   1465         456
2   01/04/2013  20/01/2014  8   14658        4586
2   29/04/2013  20/01/2014  7   146587       45876

Существуют дополнительные сложные логические элементы, такие как запуск кумуляции только тогда, когда дата начала предшествует дате окончания предыдущей строки, поэтому ключевым является решение, которое обеспечивает гибкость путем добавления операторов where или case when.

Пример рекурсивного CTE и функции упорядочения, которые я использовал (не адаптированные для показанной упрощенной таблицы, но указывающие на структуру, которую я использовал) приведены ниже.

Рекурсивный CTE (столбец шага вывода 1)

with t (ID, Segment,start_date, start_comb,updated_end_date ,rn) as (
            select ID, Segment, start_date, case when Segment_end_date <> resolved_date OR Segment_end_date is null then 1 else 0 end as start_comb
                                                    ,updated_end_date
                                                    ,row_number() over (partition by ID order by start_date) as rn
                                                    from #test_IDs
) 

,r (ID, orig_seg, Segment, rn, start_comb, start_date, updated_end_date) as (

  select ID, cast(Segment as varchar(max)), cast(Segment as varchar(max)),rn, start_comb, start_date, updated_end_date
  from t
  where start_comb=0
  union all
  select r.ID, cast(t.segment as varchar(max)) as orig_seg
  , Segment = cast( (concat(r.Segment,t.Segment)) as varchar(max))
  , t.rn, t.start_comb, t.start_date, t.updated_end_date
  from r
  join t on t.ID = r.ID and t.rn = r.rn + 1 and t.start_comb <> 0 
)

Функция заказа (столбец шага 2 вывода)


if object_id ('reformat') is not null
drop function reformat

create function dbo.reformat
( 
    @unordered_Segs varchar(max)
)
returns varchar(255)
as
begin

    declare @healthy int, @first int, @second int, @third int, @fourth int, @fifth int, @outtext int

    if Charindex('4',@unordered_segs)  > 0 

            set @first = 4
            else set @first = ''
    if Charindex('5',@unordered_segs)  > 0

            set @second = 5
            else set @second = ''
    if Charindex('8',@unordered_segs)  > 0

            set @third = 8
            else set @third = ''
    if Charindex('7',@unordered_segs)  > 0

            set @fourth = 7
            else set @fourth = ''
    if Charindex('6',@unordered_segs)  > 0

            set @fifth = 6
            else set @fifth = ''

    if Charindex('1',@unordered_segs)  > 0 and len(@unordered_segs) = 1
            set @outtext = 1
            else
    set @outtext = Replace((concat(@first,@second,@third,@fourth,@fifth)),'0','')

return      @outtext
end

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...