我有一个存储用户聊天消息的表。每个消息都记录在此表中。我必须计算特定用户的聊天持续时间。
由于用户可能在x时间聊天,并且在x + 10次后他离开聊天。在X + 20时间之后,用户再次开始聊天。因此,不应考虑x + 10和x + 20之间的时间段。
表格结构和样本数据如图所示。不同的颜色代表同一用户的两个聊天会话。我们可以看到在663和662之间存在超过1小时的差异,因此应该从结果集中排除这些会话。最终结果应该是2.33分钟。
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
请建议一个计算聊天时间的解决方案。这是我能想到的逻辑之一,以防你们中的任何一个人有更好的想法。请与解决方案分享
答案 0 :(得分:2)
首先需要计算相邻消息之间的差距,如果差距超过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
答案 1 :(得分: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上设置了一个工作示例。如果您有任何问题,请查看并告诉我。
答案 2 :(得分: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
角度查看“用户”,但考虑到在聊天期间,用户可以是发件人或收件人。
答案 3 :(得分:0)
您可以使用此查询(here):
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
答案 4 :(得分:0)
我专注于对表结构进行细微修改并更新聊天服务器应用程序代码(如果可能的话)。
每次超过X分钟的消息之间有延迟时,您是否可以让聊天服务器生成新的聊天ID?如果是,那么计算聊天持续时间将变得非常容易。