2011-08-03 17 views
1

私はこのDB構造ました:クエリーで結合すると、コントロール:それは可能ですか?

Message 

msg_by  usertype  message  
2    U   how are you ? 
1    A   i'm fine 


SimpleUser 

id   fullname  
1   mike  
2   john 


AdminUser  

id   fullname 
1   frank  
2   lucas 

[OK]を、私はそれが2つのテーブルにユーザーを分割することは正しくないと知っているが、私はこのプロジェクトを継承しました。

私の質問は、SimpleUserとAdminUserでMessageに参加するクエリを作成する方法です。結果はusertypeに基づいて各メッセージに正しい名前を付けます:メッセージがSimpleUserテーブルからのものであれば、AメッセージはAdminUserからです

ありがとうございました! UNION

答えて

4

SELECT fullname, message FROM msg_by JOIN SimpleUser ON(msg_by = SimpleUser.id) 
    WHERE usertype = "U" 

UNION ALL 

SELECT fullname, message FROM msg_by JOIN AdminUser ON(msg_by = AdminUser.id) 
    WHERE usertype = "A" 
+0

私はあなたを愛しています、S.O.みんな! – stighy

+0

注:結果を組み合わせるのではなく、UNIONを使用してインラインビューを作成すると、より高速で、より一般的で移植性が向上する可能性があります。そして、UNION ALLを使用することは、ほぼ確実に高速です。すべて同じ、+1: – MatBailie

+0

@Dems:ありがとう! 'UNION ALL'はもっと良く編集されました!とにかく、データベースが "継承"されているとすれば、インラインビューの提案は他の状況のOPにも役立つかもしれません。 –

4

これは、あなたがしたい行を返します1つのクエリです:

SELECT 
    msg_by, usertype, message, full_name 
FROM 
    Message 
INNER JOIN 
    SimpleUser 
ON 
    SimpleUser.id = Message.msg_by 
AND 
    Message.usertype = 'U' 

UNION ALL 

SELECT 
    msg_by, usertype, message, full_name 
FROM 
    Message 
INNER JOIN 
    AdminUser 
ON 
    AdminUser.id = Message.msg_by 
AND 
    Message.usertype = 'A' 
+0

'UNION'の代わりに' UNION ALL'を使うと+1 – MatBailie

2

あなたは労働組合を必要としません。そのような

select 
    m.*, 
    ifnull(a.full_name, s.full_name) 
from 
    Message m 
    left join AdminUser a on a.id = m.msg_by and m.usertype = 'A' 
    left join SimpleUser s on s.id = m.msg_by and m.usertype = 'U' 
+0

Downvote?どうして? – GolezTrol

1

を何か:あなたが参加するユーザタイプを追加することができます個人的に

SELECT m.message, COALESCE(s.fullname, a.fullname) 
FROM Message m 
    LEFT OUTER JOIN SimpleUser s 
     ON m.usertype = 'U' 
     AND m.msg_by = s.id 
    LEFT OUTER JOIN AdminUser a 
     ON m.usertype = 'A' 
     AND m.msg_by = a.id 
1

、私の自然な傾斜がアプローチに参加LEFTを使用することです。

考慮して、しかし、UNIONアプローチは最良であってもよい - 代わりにインライン・ビューとしてレイアウトされた場合...

SELECT 
    Message.*, 
    User.* 
FROM 
    Message 
INNER JOIN 
(
    SELECT *, 'A' as UserType From AdminUsers 
    UNION ALL 
    SELECT *, 'U' AS UserType FROM SimpleUsers 
) 
    AS User 
    ON User.UserType = Message.UserType 
    AND User.ID  = Message.msg_by 

起因して、より良い性能で、このインライン・ビューのレイアウトをよい結果を使用します一度だけメッセージテーブルをスキャンする必要があります。

また、2つのテーブルを統合するために実際のビューを作成するオプションを指示します。

+0

Messageとsubselectの内部結合が索引を利用できない可能性があるため、パフォーマンスは向上する可能性がありますが、遅くなることもあります。しかし、あなたが言うように、テスト(そして計画をチェックすること)は疑問に答えるでしょう。 :) – GolezTrol

+0

私の経験では、この方法でUNION ALLを使用すると、INDEXesの使用が維持されます。 UNIONの使用(およびその重複排除)は重複排除ルーチンなので、別の問題になる可能性があります。しかし、それはすべてRDBMSのエンジンに依存しており、知るにはテストすることです:) – MatBailie

関連する問題