Как связать всех детей с родителями, используя таблицу «Один ко многим» в SQL? - PullRequest
1 голос
/ 04 февраля 2012

Я пытаюсь написать SQL-запрос, который связывает сегменты вызовов вместе, динамически создавая уникальный столбец CallID.Для этого в базе данных используются две таблицы: таблица сегментов вызовов и таблица связей сегментов вызовов, которая является таблицей связи «один ко многим».Один сегмент вызова может связываться со многими другими сегментами вызова.Не все сегменты вызовов имеют записи в таблице ссылок сегментов вызовов.Ссылка на сегмент вызова создается только в случае передачи вызова.

Я использую SQL Server 2008 R2.Моя конечная цель - закончить запросом, который выводит одну строку для каждого сегмента вызова с одним дополнительным столбцом Идентификатор вызова (идентификатор первого сегмента вызова).

Если кто-либо имеет представление о том, как это возможнос SQL, я был бы очень признателен за помощь.

Спасибо!

Calls

Структура таблицы: CallSegment - CallSegmentID

CallSegmentLink - CallSegmentLinkID- CallSegmentParentID - CallSegmentChildID

1 Ответ

2 голосов
/ 05 февраля 2012

В то время как сегменты последовательного вызова допускают обработку с помощью CTE, сегменты параллельного вызова создают довольно серьезный камень.

Следующий код назначит номера вызовов каждому вызову и соответствующим образом сгруппирует сегменты вызова:

-- Set up the test data.
declare @CallSegments as table ( CallSegmentId int )
insert into @CallSegments ( CallSegmentId ) values ( 1 ), ( 2 ), ( 3 ), ( 4 ), ( 5 ), ( 6 ), ( 7 ), ( 8 )

declare @CallSegmentLinks as table ( ParentCallSegmentId int, ChildCallSegmentId int )
insert into @CallSegmentLinks ( ParentCallSegmentId, ChildCallSegmentId ) values
  ( 1, 2 ), ( 2, 3 ), ( 3, 4 ),
  ( 6, 7 ), ( 6 , 8 )

-- Find all of the   CallSegments   which are not targets of   CallSegmentLinks   and assign a   CallNumber   to each.
declare @Calls as table ( InitialCallSegmentId bit, CallSegmentId int, CallNumber int )
insert into @Calls
  select 1, CallSegmentId, Row_Number() over ( order by CallSegmentId ) as CallNumber
    from @CallSegments
    where not exists ( select 42 from @CallSegmentLinks where ChildCallSegmentId = CallSegmentId )

-- Add the remaining call segments.
insert into @Calls
  select 0, CallSegmentId, NULL
    from @CallSegments
    where CallSegmentId not in ( select CallSegmentId from @Calls )

-- Propogate the   CallNumber   to the remaining call segments.
while ( @@RowCount > 0 )
  begin
  update Child
    set CallNumber = Parent.CallNumber
    from @Calls as Parent inner join
      @CallSegmentLinks as CSL on CSL.ParentCallSegmentId = Parent.CallSegmentId inner join
      @Calls as Child on Child.CallSegmentId = CSL.ChildCallSegmentId
    where Child.CallNumber is NULL and Parent.CallNumber is not NULL
  end

-- Display the grouped call segments with the initial call segment for each call shown first.
select * from @Calls order by CallNumber, InitialCallSegmentId desc, CallSegmentId

Обратите внимание, что первый сегмент вызова в каждом вызове помечен.Это может помочь вам написать дополнительный код, который отслеживает сегменты в вызове в заказе или по вашему собственному замыслу.

...