4

I have a table which stores chat messages for users. Every message is logged in this table. I have to calculate chat duration for a particular user.

Since there is a possibility that user is chatting at x time and after x+10 times he leaves chatting. After X+20 time, again user starts chatting. So the time period between x+10 and x+20 should not be accounted.

Table structure and sample data is as depicted. Different color represent two chat sessions for same user. As we can see that between 663 and 662 there is a difference of more than 1 hour, so such sessions should be excluded from the resultset. Final result should be 2.33 minutes.

enter image description here

declare @messagetime1 as datetime
declare @messagetime2 as datetime
select @messagetime1=messagetime from tbl_chatMessages where ID=662
select @messagetime2=messagetime from tbl_chatMessages where ID=659
print datediff(second,@messagetime2,@messagetime1)
   Result --- 97 seconds

declare @messagetime3 as datetime
declare @messagetime4 as datetime
select @messagetime3=messagetime from tbl_chatMessages where ID=668
select @messagetime4=messagetime from tbl_chatMessages where ID=663
print datediff(second,@messagetime4,@messagetime3)
   Result -- 43 seconds

Please suggest a solution to calculate duration of chat. This is one of the logic I could think of, in case any one of you has a better idea. Please share with a solution

4

5 回答 5

2

首先需要计算相邻消息之间的gap,如果gap超过600秒,那么这些消息之间的时间为0

SELECT SUM(o.duration) / 60.00 AS duration
FROM dbo.tbl_chatMessages t1
  OUTER APPLY (
               SELECT TOP 1 
                 CASE WHEN DATEDIFF(second, t2.messageTime, t1.messageTime) > 600
                      THEN 0 
                      ELSE DATEDIFF(second, t2.messageTime, t1.messageTime) END
               FROM dbo.tbl_chatMessages t2
               WHERE t1.messageTime > t2.messageTime
               ORDER BY t2.messageTime DESC
               ) o(duration)

见演示SQLFiddle

于 2013-08-04T23:14:25.557 回答
0

尝试这样的事情:

WITH DATA 
     AS (SELECT t1.*, 
                CASE 
                  WHEN 
        Isnull(Datediff(MI, t2.MESSAGETIME, t1.MESSAGETIME), 11) > 10 
                   THEN 0 
                  ELSE 1 
                END first_ident 
         FROM   TABLE1 t1 
                LEFT JOIN TABLE1 t2 
                       ON t1.ID = t2.ID + 1), 
     CTE 
     AS (SELECT ID, 
                MESSAGETIME, 
                ID gid, 
                0  AS tot_time 
         FROM   DATA 
         WHERE  FIRST_IDENT = 0 
         UNION ALL 
         SELECT t1.ID, 
                t1.MESSAGETIME, 
                t2.GID, 
                t2.TOT_TIME 
                + Datediff(MI, t2.MESSAGETIME, t1.MESSAGETIME) 
         FROM   DATA t1 
                INNER JOIN CTE t2 
                        ON t1.ID = t2.ID + 1 
                           AND t1.FIRST_IDENT = 1) 
SELECT GID, 
       Max(TOT_TIME) Tot_time 
FROM   CTE 
GROUP  BY GID 

我在SQL Fiddle上设置了一个工作示例。看看,如果您有任何问题,请告诉我。

于 2013-08-04T20:10:29.747 回答
0

这是我的解决方案背后的原因。首先,识别开始聊天期的每个聊天。您可以使用标识与上一次聊天超过 10 分钟的聊天的标志来执行此操作。

然后,取这个标志并做一个累积和。该总和实际上用作聊天时段的分组标识符。最后,汇总结果以获取每个聊天时段的信息。

with cmflag as (
      select cm.*,
             (case when datediff(min, prevmessagetime, messagetime) > 10
                   then 0
                   else 1
              end) as ChatPeriodStartFlag
      from (select cm.*,
                   (select top 1 messagetime
                    from tbl_chatMessages cm2
                    where cm2.senderId = cm.senderId or
                          cm2.RecipientId = cm.senderId
                   ) as prevmessagetme
            from tbl_chatMessages cm
           ) cm
     ),
     cmcum as (
      select cm.*,
             (select sum(ChatPeriodStartFlag)
              from cmflag cmf
              where cm2.senderId = cm.senderId or
                    cm2.RecipientId = cm.senderId and
                    cmf.messagetime <= cm.messagetime
             ) as ChatPeriodGroup
      from tbl_chatMessages cm
     )
select cm.SenderId, ChatPeriodGroup, min(messageTime) as mint, max(messageTime) as maxT
from cmcum
group by cm.SenderId, ChatPeriodGroup;

我可能不完全理解的一个挑战是您如何在发件人和收件人之间进行匹配。样本数据中的所有行都具有相同的对。这是从SenderId角度来看“用户”,但考虑到在聊天期间,用户可能是发送者或接收者。

于 2013-08-05T00:58:59.813 回答
0

您可以使用此查询(此处):

DECLARE @Results TABLE(
  RowNum INT NOT NULL,
  senderID INT NOT NULL DEFAULT(80),
  recipientID INT NOT NULL DEFAULT(79),
    PRIMARY KEY(RowNum,senderID,recipientID),
  messageTime DATETIME NOT NULL
);
INSERT INTO @Results(RowNum,senderID,recipientID,messageTime)
SELECT  ROW_NUMBER() OVER(PARTITION BY senderID,recipientID ORDER BY messageTime, ID) AS RowNum,
        c.senderID,c.recipientID,c.messageTime
FROM    dbo.tbl_chatMessages c;

WITH RecursiveCTE
AS(
    SELECT  crt.RowNum,crt.senderID,crt.recipientID,
            crt.messageTime,
            1 AS SessionID
    FROM    @Results crt
    WHERE   crt.RowNum=1
    UNION ALL
    SELECT  crt.RowNum,crt.senderID,crt.recipientID,
            crt.messageTime,
            CASE 
                WHEN DATEDIFF(MINUTE,prev.messageTime,crt.messageTime) <= 10  THEN prev.SessionID
                ELSE prev.SessionID+1
            END
    FROM    @Results crt INNER JOIN RecursiveCTE prev ON crt.RowNum=prev.RowNum+1
    AND     crt.senderID=prev.senderID
    AND     crt.recipientID=prev.recipientID
)
SELECT  *,
        STUFF(CONVERT(VARCHAR(8), DATEADD(SECOND,x.SessionDuration,0), 114), 1,3,'') AS SessionDuration_mmss,
        SUM(x.SessionDuration) OVER() AS SessionDuration_Overall,
        STUFF(CONVERT(VARCHAR(8), DATEADD(SECOND,SUM(x.SessionDuration) OVER(),0), 114), 1,3,'') AS SessionDuration_Overall_mmss
FROM(
    SELECT  r.senderID,r.recipientID,r.SessionID, 
            DATEDIFF(SECOND, MIN(r.messageTime),MAX(r.messageTime)) AS SessionDuration
    FROM    RecursiveCTE r
    GROUP BY r.senderID,r.recipientID,r.SessionID
) x
OPTION(MAXRECURSION 0);

结果:

senderID recipientID SessionID   SessionDuration SessionDuration_mmss SessionDuration_Overall SessionDuration_Overall_mmss
-------- ----------- ----------- --------------- -------------------- ----------------------- ----------------------------
80       79          1           97              01:37                140                     02:20
80       79          2           43              00:43                140                     02:20
于 2013-08-05T06:06:35.337 回答
0

我将专注于表结构的细微修改和更新聊天服务器应用程序代码(当然如果可能的话)。

每次消息之间的延迟超过 X 分钟时,您能否让聊天服务器生成新的聊天 ID?如果是,那么计算聊天时长将变得非常容易。

于 2013-08-05T09:12:34.867 回答