2012-03-27 7 views
1

説明を簡単にするために、メンバーテーブルとメールテーブルを使用します。メールテーブルには、次の構造を有する:ON句が可変のときに2つのテーブルを結合する方法

------------------------------- 
FromMember int NOT NULL (FK) 
ToMember int NOT NULL (FK) 
... 
------------------------------- 

は、私は彼がFromMemberかToMemberであるかどうかを特定のメンバーのためにすべてのメールを返しますクエリを書きたいです。 WHERE句にOR句を使用するのは簡単です。

しかし、それは複雑になる私はメンバーのメンバー情報を取得するために、メンバテーブルにメールテーブルに参加したいということです。したがって、私がFromMemberである場合、メンバーテーブルへのジョイン句はToMemberフィールドを使用し、私がToMemberである場合、ジョイン句よりもFromMemberフィールドを使用します。基本的に、ON句は特定の条件に基づいて2つの異なるフィールドと結合する必要があります。それは可能ですか?

SELECT * FROM mail INNER JOIN member ON mail.ToMember = member.MemberID 
WHERE mail.FromMember = @me 
UNION ALL 
SELECT * FROM mail INNER JOIN member ON mail.FromMember = member.MemberID 
WHERE mail.ToMember = @me 

しかし、私は結果セットが私のコードの多くの場所で使用されるため、ビューでこのクエリを入れたいと思います:

私のソリューションは、これまで次のようにALL UNIONを使用することです。つまり、ユーザー定義の表関数を使用して実装する必要があると考えられるパラメータ化されたビューが必要です。

基本的に、私は2つの答えを探しています:
UNION ALLの代わりにそのクエリを書く方が良いですか?
また、そのクエリをVIEWまたはUDFに配置する必要がありますか?

VIEWが推奨される方法である場合、どのように@meパラメータをVIEWに渡すことができますか。 @me paramをWHERE節に移動することはできません。なぜなら、WHERE節はON節に依存しているからです。 WHERE句を引き出し、それらをOR演算しても、上記のUNION ALLクエリと同じ結果セットは返されません。

+0

UNION ALLを含むビューを作成できます。何故なの? – JotaBe

+0

**解答の中で「OR」を示唆している人は、インデックスを使用せずにテーブル全体をスキャンするだけです**これは行の数や回数に応じて痛いものになる可能性がありますこのクエリが実行されます。 'UNION'を使用すると、' FromMember'と 'ToMember'の両方でインデックスヒットが可能になります(存在すれば)。私の経験では、ほとんどの場合、インデックスを使用することはテーブルスキャンよりもずっと速くなります。 –

+0

@KM:上記の "OR"文はINNER JOIN ON句のOR句にも適用されますか? @quazaryによって以下の答えで指定されているように? – Cristina

答えて

3

1.

SELECT * 
FROM mail 
    INNER JOIN member 
    ON (mail.FromMember = @me and mail.ToMember = member.MemberID) 
    or (mail.ToMember = @me and mail.FromMember = member.MemberID) 
  1. 通常のビューが速いのUDF、その後ですが。
+0

Duh、私は基本的にはどこで私のORを作ることでそれを行い、単純化を見ていない。 +1 –

+0

@meパラメータをビューにどのように送信すればよいですか? – Cristina

+0

パラメータは必要ありません。あなたのビューをどこでフィルタリングしますか? – JotaBe

1

あなたのクエリを反転し、このような何か実行する必要があります。

SELECT member.* 
FROM member 
    LEFT JOIN mail AS ToMail 
     ON ToMail.ToMember = member.MemberID AND ToMail.ToMember = @me 
    LEFT JOIN mail AS FromMail 
     ON FromMail.FromMember = member.MemberID AND FromMail.ToMember = @me 
WHERE ToMail.ToMember IS NOT NULL OR FromMail.FromMember IS NOT NULL 
1

私はT-SQLがパラメータ化されたビューを実行するとは思わない。この機能は、インライン・テーブル関数を介して処理されます。あなたの問題を処理する関数は以下のとおりです。

CREATE FUNCTION fExample_GetRelatedMailMembersForMember 
(
    @MemberId INT 
) 
RETURNS TABLE 
AS 
RETURN 
SELECT 
    * -- Replace this with explicit columns 
FROM mail M 
INNER JOIN member MBR 
    ON MBR.MemberID IN (M.FromMember, M.ToMember) 
    AND MBR.MemberID <> @MemberId 
WHERE M.MemberId = @MemberId 
+0

のメールテーブルにフィールドMemberIDが含まれていないビューとして使用できます。FromMemberフィールドとToMemberフィールドのみが含まれています。したがって、WHERE句を定義したままにすることはできません。私はあなたのソリューションに何かを見逃していますか? – Cristina

+0

@クリスティーナ私はあなたがすでに答えを受け入れたことを知っていますが、私は先に進み、歴史のために私を決めました。あなたが送ったメンバーidではない 'member'に参加しようとしていたので、@MemberIdに変更するだけでした。あなたのために働く解決策を見つけられたらうれしいです。 :) –

+0

は、WHERE句を読んではいけません。WHERE m.FromMember = "@me" OR m.ToMember = "@me"ちょうど私が自分の知識ベースのためにこの例を得ていることを確認したい! – Cristina

0

UNION ALLクエリは問題ありません。ほぼそのままの状態にしてください。上記@JotaBeで述べたように

CREATE VIEW myView AS 
SELECT * FROM mail INNER JOIN member ON mail.ToMember = member.MemberID 
UNION ALL 
SELECT * FROM mail INNER JOIN member ON mail.FromMember = member.MemberID 

その後、メールを見て、あなたが望んだ場合には、チェーンを作成するためにWHERE句

SELECT * FROM myView WHERE ToMember = @me OR FromMember = @me 

あなたはまた、クエリーで一緒に結合ビューの可能性を使用してビューを照会あるメンバーから別のメンバーに渡されたメッセージ。

関連する問題