我继承了一个使用SQL Server(2008 R2)的系统,其中包含两个涵盖系统消息传递的表。消息具有一对多关系,可以发送给多个用户。
主表,Messaging,如下所示:
Id (PK, auto increment)
Subject
MessageBody
CreatorEmployeeId
ConversationId
IsConversationStarter (bool)
辅助表,MessagingDetails,如下所示:
ID (PK, auto increment)
MessageId (FK to Messaging PK)
RecipientEmployeeId
ConversationId
IsRead (bool)
如果不清楚,则会在Messaging表中添加一条新消息,其中包含创建该消息的员工ID,并创建新的Conversation Id。然后将X行数插入到MessagingDetails中,每个收件人一个,引用返回Messaging表并使用相同的Conversation Id。
任何新回复看起来都一样,回复消息进入Messaging表,收件人详细信息使用相同的Conversation Id进入MessagingDetails,这样您就可以将整个消息线程拉一个数字。
当您尝试计算已创建或已发送给您的所有未读邮件时,这会变得草率。这是一个现有查询,它可以获取系统中其他用户发送给登录用户的所有未读消息,他们最初创建消息:
SELECT * FROM dbo.Messaging m
INNER JOIN dbo.MessagingDetails m1 on m.Id = m1.MessageId
INNER JOIN dbo.MessagingDetails m2 on m1.ConversationId = m2.ConversationId
WHERE m1.RecipientEmployeeId = @employeeId
AND m.IsConversationStarter = 1
AND m.ConversationId = m1.ConversationId
AND m2.IsRead = 0
AND m2.RecipientEmployeeId == @employeeId
然后,要查找员工创建但有未读回复的所有消息,您必须执行几乎相同的查询,将WHERE
子句的第一部分换成:
m.CreatorEmployeeId = @employeeId
我厌恶内心加入同一张桌子两次,一次对自己。鉴于上面概述的架构,是否有更好的方法来编写这些查询?
答案 0 :(得分:1)
为了摆脱dbo.MessagingDetails
的第二次加入,此查询应与您的查询等效。
SELECT * FROM dbo.Messaging m
INNER JOIN dbo.MessagingDetails m1 on m.Id = m1.MessageId
WHERE m1.RecipientEmployeeId = @employeeId
AND m.IsConversationStarter = 1
AND m.ConversationId = m1.ConversationId
AND EXISTS(SELECT * FROM dbo.MessagingDetails m2
WHERE m1.ConversationId = m2.ConversationId
AND m2.IsRead = 0 AND m2.RecipientEmployeeId == @employeeId)
我认为它不会更有效率,你必须检查执行计划。
答案 1 :(得分:1)
对于“有未发送回复的员工发送的消息”,我认为这解决了问题:
with EmployeeCreatedMessages as (
select distinct MessageId
from Messaging
where m.CreatorEmployeeId = @employeeId
)
select distinct MessageId
from MessageDetails md
where md.MessageId in (select MessageId from EmployeeCreatedMessages) and
md.IsRead = false
我不确定您想要了解有关该消息的信息。这只是给出了消息ID。
同样的方法适用于其他人发送给用户的所有消息:
with OtherCreatedMessages as (
select distinct MessageId
from Messaging
where m.CreatorEmployeeId <> @employeeId
)
select distinct MessageId
from MessageDetails md
where md.MessageId in (select MessageId from OtherCreatedMessages) and
md.IsRead = false and
md.RecipientEmployeeId = @employeeid
您的描述和问题未提及conversionid。这有关系吗?