有没有更好的方法来编写这些查询? (内部错误的SQL消息传递模式......)

时间:2012-08-11 15:03:23

标签: sql sql-server-2008 schema relational-database

我继承了一个使用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

我厌恶内心加入同一张桌子两次,一次对自己。鉴于上面概述的架构,是否有更好的方法来编写这些查询?

2 个答案:

答案 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。这有关系吗?