Таблица состоит из столбцов Call_party и Call_party, и запись описывает соединение между двумя пользователями, где один играет роль вызывающей стороны, а другой называется вызывающей стороной.
Одни и те же два пользователя могут иметь два соединения - в этом случае роли вызывающей / вызываемой стороны переключаются при изменении направления.
В исходной таблице (month_connections) я добавил дополнительные столбцы common_neighbors и total_neighbors, в которых хранится количество общих и общих соседей. Чтобы уточнить термины common и total_neighbors, я добавил следующее изображение:

В этом случае для наблюдаемого соединения есть 2 общих соседа вызывающей и вызываемой стороны и 6 общих соседей.
Чтобы получить эти два значения, я написал следующую хранимую процедуру:
CREATE PROCEDURE [dbo].[spCountNeighbors]
AS
Declare
@CallingParty varchar(50),
@CalledParty varchar(50),
@RecordsUpdated int
SET @CallingParty ='a'
SET @RecordsUpdated = 0
PRINT GETDATE()
WHILE @CallingParty IS NOT NULL BEGIN
SET @CallingParty = NULL
SELECT TOP 1 @CallingParty = calling_party, @CalledParty = called_party FROM monthly_connections WHERE common_neighbors IS NULL
--PRINT @CallingParty
IF @CallingParty IS NOT NULL BEGIN
WITH callingPartyNeighbors AS
(
SELECT called_party as neighbor FROM monthly_connections WHERE calling_party = @CallingParty
UNION
SELECT calling_party as neighbor FROM monthly_connections WHERE called_party = @CallingParty
),
calledPartyNeighbors AS
(
SELECT calling_party as neighbor FROM monthly_connections WHERE called_party = @CalledParty
UNION
SELECT called_party as neighbor FROM monthly_connections WHERE calling_party = @CalledParty
)
UPDATE mc SET common_neighbors = (SELECT COUNT (*) FROM
(
SELECT neighbor FROM callingPartyNeighbors
INTERSECT
SELECT neighbor FROM calledPartyNeighbors
)
t1
),
total_neighbors = (SELECT COUNT (*) FROM
(
SELECT neighbor FROM callingPartyNeighbors
UNION
SELECT neighbor FROM calledPartyNeighbors
)
t2
)
FROM monthly_connections mc WHERE (mc.calling_party = @CallingParty AND mc.called_party = @CalledParty) OR (mc.called_party = @CallingParty AND mc.calling_party = @CalledParty);
SET @RecordsUpdated = @RecordsUpdated + @@ROWCOUNT
PRINT @RecordsUpdated
END
END
PRINT @RecordsUpdated
Предполагается, что описанная выше процедура проходит через таблицу соединений, которая содержит 23M соединений, и обновляет значения common_neighbors и total_neighbors для каждой строки. Проблема, однако, в том, что процедура слишком медленная - для обновления 1000 записей потребовалось 212 с.
Буду очень признателен, если кто-нибудь из вас предложит какое-либо исправление для описанной выше процедуры, чтобы ускорить время выполнения.
Спасибо!