Попробуйте:
SELECT
T1.SrcAddress,
T1.SrcPort,
T1.DestAddress,
T1.DestPort,
T1.Bytes + COALESCE(T2.Bytes, 0) AS TotalBytes,
T1.Bytes AS A_to_B,
COALESCE(T2.Bytes, 0) AS B_to_A
FROM (
SELECT SrcAddress, SrcPort, DestAddress, DestPort, SUM(Bytes) AS Bytes
FROM PacketHeaders
GROUP BY SrcAddress, SrcPort, DestAddress, DestPort) AS T1
LEFT JOIN (
SELECT SrcAddress, SrcPort, DestAddress, DestPort, SUM(Bytes) AS Bytes
FROM PacketHeaders
GROUP BY SrcAddress, SrcPort, DestAddress, DestPort) AS T2
ON T1.SrcAddress = T2.DestAddress
AND T1.SrcPort = T2.DestPort
AND T1.DestAddress = T2.SrcAddress
AND T1.DestPort = T2.SrcPort
WHERE T1.SrcAddress < T1.DestAddress OR
(T1.SrcAddress = T1.DestAddress AND T1.SrcPort = T1.DestPort) OR
T2.DestAddress IS NULL
По данным этого теста:
CREATE TABLE PacketHeaders (ID INT, SrcAddress NVARCHAR(100), SrcPort INT, DestAddress NVARCHAR(100), DestPort INT, Bytes INT);
INSERT INTO PacketHeaders (ID, SrcAddress, SrcPort, DestAddress, DestPort, Bytes) VALUES
(1, '10.0.25.1', 255, '10.0.25.50', 500, 64),
(2, '10.0.25.50', 500, '10.0.25.1', 255, 80),
(3, '10.0.25.50', 500, '10.0.25.1', 255, 16),
(4, '75.48.0.25', 387, '74.26.9.40', 198, 72),
(5, '74.26.9.40', 198, '75.48.0.25', 387, 64),
(6, '10.0.25.1', 255, '10.0.25.50', 500, 48),
(7, '10.0.25.2', 255, '10.0.25.50', 500, 48),
(8, '10.0.25.52', 255, '10.0.25.50', 500, 48);
Это дает следующие результаты:
'10.0.25.1', 255, '10.0.25.50', 500, 208, 112, 96
'10.0.25.2', 255, '10.0.25.50', 500, 48, 48, 0
'10.0.25.52', 255, '10.0.25.50', 500, 48, 48, 0
'74.26.9.40', 198, '75.48.0.25', 387, 136, 64, 72
То, как это работает, заключается вПервая группа односторонних разговоров и общее количество байтов.Это гарантирует, что каждый разговор будет представлен ровно дважды - по одному разу для каждого направления.Затем этот результат самосоединяется, чтобы получить нужный вам результат, фильтруя дубликаты, следя за тем, чтобы (адрес, порт) A был меньше B. Для соединения в одном направлении используется левое соединение.