2010-02-02 4 views
10

IP 패킷 헤더 테이블이 포함 된 SQL 압축 데이터베이스가 있습니다. 표는 다음과 같습니다.SQL 행 결합

Table: PacketHeaders  

ID SrcAddress SrcPort DestAddress DestPort Bytes 
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 

로컬 네트워크에서 '대화'를 표시하려면 쿼리를 수행해야합니다. A -> B에서 오는 패킷은 B -> A에서 오는 패킷과 동일한 대화의 일부입니다. 진행중인 대화를 표시하기 위해 쿼리를 수행해야합니다. 당신은 내가 쿼리를 필요로 (또는 쿼리의 시리즈) 그 A-를 인식 볼 수 있듯이

Returned Query: 

SrcAddress SrcPort DestAddress DestPort TotalBytes BytesA->B BytesB->A 
10.0.25.1 255  10.0.25.50 500  208   112  96 
75.48.0.25 387  74.26.9.40 198  136   72   64 

> B가> B- 같은 A와 헤어되어 기본적으로 내가 필요한 것은 다음과 같습니다 일입니다 그에 따라 바이트 수가 계산됩니다. 나는 어떤 의미에서 SQL 전문가가 아니지만 이것에 대한 도움을 주시면 대단히 감사하겠습니다.

답변

3

이 시도 :

'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 

작동 방법은 첫 번째 그룹 단방향 대화에 : 이것은 다음과 같은 결과를 얻을 수

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); 

:이 테스트 데이터에

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 

을 총 바이트 수. 이렇게하면 모든 대화가 정확히 두 번 (각 방향에 한 번) 표시됩니다. 그런 다음이 결과를 자체 조인하여 필요한 결과를 제공하고 A의 (주소, 포트)는 B보다 작아야합니다. 왼쪽 조인은 단방향 대화를 허용하는 데 사용됩니다.

+0

각 경로가 정 반대의 항목을 가지고 있다고 가정합니다. 그래서 모두 OUTER JOIN이되어야합니다. 그러면 GROUP BY ISNULL (T1.SrcAddress, T2.DestAddress) 등이 필요합니다. – MatBailie

+0

수정으로 외부 GROUP BY 등이 제거되었습니다.모든 패킷이 반대 방향으로가는 패킷에 해당하는 경우에만 작동합니다. (그러나 그 조건이 사실이라면, 그것은 효과가 있다고 생각합니다 ...) – MatBailie

+0

이것은 양방향 대화에서만 작동합니다. 모든 대화가 양방향으로 이루어지는 것은 아닙니다. 어떻게 이것을 막기 위해 조인을 수정할 수 있습니까? – lumberjack4

3

이 작업을 수행하는 두 가지 기본 방법을 볼 수 있습니다.
1. a-> b 및 b-> a를 무시한 다음 결과를 자체 조인합니다.
2. 'src'필드에 "최저"IP 주소로 데이터를 재 배열하고 'direction'필드도 생성하십시오.

옵션 2

SELECT 
    SrcAddress, 
    SrcPort, 
    DestAddress, 
    DestPort, 
    SUM(AtoB) + SUM(BtoA), 
    SUM(AtoB), 
    SUM(BtoA) 
FROM 
(
    SELECT 
     CASE WHEN SrcAddress < DestAddress THEN SrcAddress ELSE DestAddress END AS SrcAddress, 
     CASE WHEN SrcAddress < DestAddress THEN SrcPort  ELSE DestPort END AS SrcPort, 
     CASE WHEN SrcAddress < DestAddress THEN DestAddress ELSE SrcAddress END AS DestAddress, 
     CASE WHEN SrcAddress < DestAddress THEN DestPort ELSE ScrPort  END AS DestPort, 
     CASE WHEN SrcAddress < DestAddress THEN Bytes  ELSE 0   END AS AtoB, 
     CASE WHEN SrcAddress < DestAddress THEN 0   ELSE Bytes  END AS BtoA 
    FROM 
     PacketHeaders 
) 
    AS [data] 
GROUP BY 
    SrcAddress, 
    SrcPort, 
    DestAddress, 
    DestPort 

편집 ... 아마 내가 가고 싶어 방법입니다

다른 답변의 몇 난을 내가 옵션 1. 이른바 버전을해야 한 ...

0명의 답변 :(

SELECT 
    ISNULL([AtoB].SrcAddress, [BtoA].DestAddress) 
    ISNULL([AtoB].SrcPort,  [BtoA].DestPort) 
    ISNULL([AtoB].DestAddress, [BtoA].SrcAddress) 
    ISNULL([AtoB].DestPort, [BtoA].SrcPort) 
    ISNULL([AtoB].Bytes,0) + ISNULL([BtoA].Bytes,0), 
    ISNULL([AtoB].Bytes,0), 
    ISNULL([BtoA].Bytes,0) 
FROM 
    (
     SELECT SrcAddress, SrcPort, DestAddress, DestPort, SUM(Bytes) AS Bytes 
     FROM  PacketHeaders 
     WHERE SrcAddress <= DestAddress 
     GROUP BY SrcAddress, SrcPort, DestAddress, DestPort 
    ) 
    AS [AtoB] 
FULL OUTER JOIN 
    (
     SELECT SrcAddress, SrcPort, DestAddress, DestPort, SUM(Bytes) AS Bytes 
     FROM  PacketHeaders 
     WHERE SrcAddress > DestAddress 
     GROUP BY SrcAddress, SrcPort, DestAddress, DestPort 
    ) 
    AS [BtoA] 
     ON [AtoB].SrcAddress = [BtoA].DestPort 
     AND [AtoB].SrcPort  = [BtoA].DestAddress 
     AND [AtoB].DestAddress = [BtoA].SrcPort 
     AND [AtoB].DestPort = [BtoA].SrcAddress 

에 대한 의견을 스팸보다 너무 아니라 그것을 이동하지만 내가 그런 식으로하지 않을 것이라고 말 했는가

+0

총 바이트 열을 보려면 다른 SELECT 문 내에이 모든 내용을 캡슐화해야합니다. 더 깨끗한 방법이 있습니까? – lumberjack4

+0

"SUM (AtoB) + SUM (BtoA)"줄을 추가했습니다 ... – MatBailie

+0

SQL Server CTE가 IsNull을 지원합니까? 이 게시물을 찾았습니다 : http://sqlserverce.org/blogs/faq/archive/2007/02/16/isnull-vs-coalesce.aspx –