根据子查询获取计数

时间:2019-05-15 21:03:30

标签: sql tsql sql-server-2016

在下面的SELECT语句中,我希望从一个表中获得COUNT个连接,在该表中,每个唯一transactionID的连接定义为1个连接。
因此,在我的COUNT个帐户中,我要检查以确保尚未建立连接(即,相同的transactionID,但主键ID较低)。

我尝试使用COUNT(DISTINCT pc.TransactionID),但问题是在每个分组(ThisDate,SiteName,UserName,Command)中都可能出现相同的transactionID,因此它多次计数某些连接。

然后我尝试加入同一张表,并使用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
    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

使用COUNT(DISTINCT pc.TransactionID)执行SELECT并删除内部联接时,结果如下(注意最后两行的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

使用SUM执行SELECT并添加内部联接时,结果是这样的(注意错误的Connections-总共应该只有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 个答案:

答案 0 :(得分:1)

不确定我是否理解正确,但是您似乎想检测最早出现的连接。您可以使用以下查询来做到这一点:

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