0

システム メッセージングをカバーする 2 つのテーブルを持つ SQL Server (2008 R2) を使用するシステムを継承しました。メッセージには 1 対多の関係があり、複数のユーザーに送信できます。

プライマリ テーブルの 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)

それが明確でない場合は、メッセージの作成者の従業員 ID を使用して新しいメッセージが Messaging テーブルに入れられ、新しい会話 ID が作成されます。次に、受信者ごとに X 行が MessagingDetails に挿入され、Messaging テーブルへの参照が返され、同じ会話 ID が使用されます。

新しい返信は同じように見え、返信メッセージは Messaging テーブルに入れられ、受信者の詳細は同じ会話 ID を使用して MessagingDetails に入れられるため、メッセージ スレッド全体を 1 つの番号で取得できます。

これは、自分が作成した、または自分に送信されたすべての未読メッセージの数を取得しようとすると、ずさんになります。システム内の他のユーザーによってログイン ユーザーに送信されたすべての未読メッセージを取得する既存のクエリを次に示します。最初にメッセージを作成した場所は次のとおりです。

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 回、1 回はそれ自体に参加する内部を嫌います。上記のスキーマを考えると、これらのクエリを記述するより良い方法はありますか?

4

2 に答える 2

1

への 2 番目の結合を取り除くために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)

これ以上効率的だとは思いませんが、実行計画を確認する必要があります。

于 2012-08-11T15:14:54.873 に答える
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 について言及していません。これは関連していますか?

于 2012-08-11T15:29:56.753 に答える