Получение подсчета в зависимости от подзапроса - PullRequest
0 голосов
/ 16 мая 2019

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

Я пытался использовать COUNT (DISTINCT pc.TransactionID), но проблема заключалась в том, что один и тот же идентификатор транзакции может встречаться в каждой группе (ThisDate, SiteName, UserName, Command), поэтому он подсчитывал некоторые соединения более одного раза.

Затем я попытался соединиться с одной и той же таблицей и использовал SUM вместо COUNT, что, похоже, работало, но это увеличило значение BytesTransferredиз-за дополнительных записей, которые были извлечены.

Идеи наилучшего способа справиться с этим?

Таблица ProtocolCommands

ProtocolCommandID, int, not null, primary key
Time_Stamp Datetime
SiteName nvarchar(50) null
UserName nvarchar(50) null
Command nvarchar(50) null
BytesTransferred numeric(18,0) null
TransactionID int not null

Оператор Select

SELECT
    CONVERT(date,pc.Time_stamp) As ThisDate,
    pc.SiteName,
    pc.UserName,
    pc.Command,
    SUM(CASE WHEN p.TransactionID IS NULL THEN 1 ELSE 0 END) As Connections,    
    -- COUNT(DISTINCT pc.TransactionID) AS Connections,
    SUM(pc.BytesTransferred) AS DataTransferred 
FROM ProtocolCommands pc
    LEFT OUTER JOIN ProtocolCommands p ON p.TransactionID = pc.TransactionID AND p.ProtocolCommandID < pc.ProtocolCommandID
WHERE pc.Time_Stamp >= '01/01/2019'
GROUP BY CONVERT(date,pc.Time_stamp),pc.SiteName, pc.UserName, pc.Command

Для примера приведем несколько записей:

Time_stamp  SiteName    UserName    Command BytesTransferred    TransactionID
2019-04-20  MySite  Joe connect 2000    12345
2019-04-20  MySite  Joe send    20000   12345
2019-04-21  MySite  Joe retrieve    25952   12345
2019-04-21  MySite  Joe send    30000   12345

При выполнении SELECT с помощью COUNT (DISTINCT pc.TransactionID) и удаление внутреннего объединения приводит к следующим результатам (обратите внимание на неправильный DataTransferred для последних двух строк):

ThisDate    SiteName    UserName    Command Connections DataTransferred
2019-04-20  MySite  Joe connect 1   2000
2019-04-20  MySite  Joe send    0   20000
2019-04-21  MySite  Joe retrieve    0   51904
2019-04-21  MySite  Joe send    0   90000

При выполнении SELECT с помощью SUM и добавлении внутреннего объединения получаются следующие результаты (обратите внимание на неправильные соединения - всего должно быть только 1):

ThisDate    SiteName    UserName    Command Connections DataTransferred
2019-04-20  MySite  Joe connect 1   2000
2019-04-20  MySite  Joe send    1   20000
2019-04-21  MySite  Joe retrieve    1   25952
2019-04-21  MySite  Joe send    1   30000

Ожидаемый результат:

ThisDate    SiteName    UserName    Command Connections DataTransferred
2019-04-20  MySite  Joe connect 1   2000
2019-04-20  MySite  Joe send    0   20000
2019-04-21  MySite  Joe retrieve    0   25952
2019-04-21  MySite  Joe send    0   30000

1 Ответ

1 голос
/ 16 мая 2019

Не уверен, правильно ли я понял, но вы, похоже, хотите обнаружить самое старое вхождение в соединение.Вы можете сделать это, используя этот запрос:

SELECT ROW_NUMBER() OVER (PARTITION BY TransactionId ORDER BY ProtocolCommandID ASC) as RowNum
, ProtocolCommandId
FROM ProtocolCommands

Это будет иметь RowNum = 1 для записи, где соединение появляется в самый первый раз.

Присоединение к основной таблице позволяет получить правильное количество соединений

SELECT 
  CONVERT(date,pc.Time_stamp) As ThisDate,
    pc.SiteName,
    pc.UserName,
    pc.Command,
    CASE WHEN first_conn.RowNum = 1 THEN SUM(first_conn.RowNum) ELSE 0 END AS Connection,
    SUM(pc.BytesTransferred) AS DataTransferred 
FROM ProtocolCommands pc
    LEFT OUTER JOIN 
        (SELECT ROW_NUMBER() OVER (PARTITION BY TransactionId ORDER BY ProtocolCommandID ASC) as RowNum
            , ProtocolCommandId
        FROM ProtocolCommands) as first_conn ON pc.ProtocolCommandID = first_conn.ProtocolCommandID

GROUP BY CONVERT(date,pc.Time_stamp),pc.SiteName, pc.UserName, pc.Command, first_conn.RowNum
...