正規化されたSQL DBを効果的にクエリして集約する方法は?
-
16-10-2019 - |
質問
に関して 単一の保存されたProcで複数の集合体を返す最も効率的な方法は?
電子メールタイプアプリケーションがあり、ユーザー用のすべてのメッセージ(受信トレイ)を選択したいと考えています。問題は、電子メールのヘッダー部分をDBに正規化して、フラットデータがメッセージテーブルに入り、from、cc、bccが別のテーブルに保存されることです。
メッセージを選択するための最良の方法は何ですか(完全に - 完全なメッセージを非正規化することを意味します)。各レコードには、すべてのメッセージテーブルフィールドを含むすべてのメッセージが含まれ、PK/に従ってメッセージに関連する受信者テーブルから関連するレコードを含むすべてのメッセージが含まれます。 FK関係。
私が多くの重量を置いていることの1つは、SQLソリューションの効率性です。
コンテキストについては、私のDBスキーマのビューです。
解決
これが私がそれをする方法です。私は定期的にCoalesceを使用して、列を区切りフィールドに配置しますが、常にパフォーマンスとスケールがあります(サブクエリが常にパフォーマンスがヒットしようとしていることに気付く限り)。
ストアドプロシージャとして実行するのが好きではない場合は、テーブルの価値のある関数として簡単に書き換えることもできます。
もう1つのアプローチはCTEだと思いますが、ゼロからタイプするアプローチに精通していません。
CREATE PROCEDURE GetMessageById
@pMessageID int
AS
BEGIN
SET NOCOUNT ON;
Declare @pTo varchar(max)
Declare @pCC varchar(max)
Declare @pBC varchar(max)
SELECT @pTo = COALESCE(@pTo + ', ', '') + [EmailAddress]
FROM MessageRecipient
WHERE MessageID = @pMessageID AND RecipientTypeID = 1 /** or whatever the id of TO field is */
SELECT @pCC = COALESCE(@pCC + ', ', '') + [EmailAddress]
FROM MessageRecipient
WHERE MessageID = @pMessageID AND RecipientTypeID = 2 /** or whatever the id of CC field is */
SELECT @pBC = COALESCE(@pBC + ', ', '') + [EmailAddress]
FROM MessageRecipient
WHERE MessageID = @pMessageID AND RecipientTypeID = 3 /** or whatever the id of BCC field is */
SELECT Message.*, @pTo as [ToField], @pCC as [CCField], @pBC as [BCCField], (SELECT TOP 1 [EmailAddress] FROM MessageRecipient Where RecipientTypeID = 0 /**<sender id>*/ AND MessageID = @pmessageID) AS [FromField] FROM Message Where Message.ID = @pMessageID
END
GO
この方法で使用したときにCoalesceがどのように機能するかを自問するかもしれません(最初に使用したのを見たとき)。基本的に、リターンセットの終了まで、セット内の各非ヌル値を返す再帰クエリを作成します。もう一方の端から出て、すべての結果のcom睡状態の区切りリストを1つの文字列として取得します。
他のヒント
呼ばれるビューを作成します viewinbox それはすべての人によって考案されています 1対1 関係表。これが私のメインクエリビューです。このビュー(ViewInbox)を使用して、すべての受信トレイアイテムのリストを表示します。
ユーザーの場合 ドリルダウンします メッセージに、次に、 1対多い 複数のTo、CC、BCCからの関係。