(Manual)InnerJoin

概要

基本概念

指定されたリレーションの結合方式を内部結合(inner join)にします。

めったに使わない

ConditionBeanの結合方式は、基本的に外部結合(left outer join)が利用されます。

ConditionBeanのポリシーとして、結合するだけでレコードが絞り込まれる ってのは避けた方がいいと考えています。なので、絞り込みを目的に、この (Manual)InnerJoin の機能は使わない方が良いでしょう。many-to-one, one-to-one の関連テーブルが存在するという絞り込みをしたいのであれば...

e.g. InnerJoinの実装手順 (Eclipseでコード補完) {MemberStatus} @Java
MemberCB cb = new MemberCB();

// 結合先のPKが存在する (つまり、結合先のデータが存在する)
cb.query().queryMemberWithdrawalAsOne().setMemberId_IsNotNull();

という風にやると良いでしょう。また、この条件を入れると InnerJoinAutoDetect の機能で自然と inner join になるので、パフォーマンス的な意味合いでの inner join も同時に満たされます。

こういった状況以外で、どうしても left outer join を強制的に inner join にしなければならないとパフォーマンスが出ない、というときに (Manual)InnerJoin を使います。

稀な状況でのパフォーマンス

ごく稀な状況で、外部結合から内部結合に変えることでパフォーマンスが改善することがあります。 例えば、数百万件を超えるデータ、古いバージョンのDBMS、様々な要素が絡み合ってそういう状況が発生する可能性があります。 そういったパフォーマンス上の調整のために、どの結合を内部結合にするかを手動で指定 (Manual)InnerJoin できるようになっています。

会話上では、いんなーじょいん もしくは まにゅあるいんなーじょいん と表現します。

InnerJoin の利用上の注意

InnerJoin は、リレーションのカージナリティ次第では、(絞り込み条件を指定していない場合でも)基点テーブルに絞り込みが発生する可能性があります。 利用する時は業務的なカージナリティをよく考慮した上で細心の注意を払って利用して下さい。以下、特に注意すべきパターンです。

  • {n : 0...1} 型リレーション (会員から見た会員退会情報、会員退会情報から見た退会理由)
  • カージナリティ的には大丈夫でも、OnClause や InlineView で絞り込みがある

もちろん、該当リレーションを使った(OnClause や InlineView ではない)絞り込み条件がある場合は、 実質的な {n : 1} 型リレーションになるため、外部結合でも内部結合でも検索結果は変わりませんので気にする必要はありません。

諸刃の剣

TwoEdgedSword 認定のされた機能です。しっかり精度高く利用しないと、逆にカオスを生み出します。 どうしても InnerJoinAutoDetect では行き届かない結合で、しかしながらそこを内部結合にすると速くなる、というケース以外での利用は想定されません。 (要は、基本的に使わないで、という感じです)

実装方法

実装の流れ

query().query[relation]() の後、innerJoin() を呼び出します。

e.g. InnerJoinの実装手順 (Eclipseでコード補完) {MemberStatus} @Java
MemberCB cb = new MemberCB();
cb.query().queryMemberStatus().setDisplayOrder_LessThan(3);
cb.query().queryMemberStatus().inn // .inn と打って enter
--
cb.query().queryMemberStatus().innerJoin(); // [何のためかコメント]

※何のための innerJoin() なのか、コメントで書きましょう。

e.g. 会員ステータスの結合を内部結合に @DisplaySql
...
  from MEMBER dfloc
    inner join MEMBER_STATUS dfrel_0 on ...
 where dfrel_0.DISPLAY_ORDER < 3

指定されたリレーションの結合が内部結合になります。呼び出すタイミングは任意ですが、 習慣的に対象となるリレーションでの絞り込み条件などを指定した後が良いでしょう。

SetupSelect(Relation) のリレーションにも適用されます。

e.g. SetupSelectしたリレーションを内部結合に {MemberStatus} @Java
MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
cb.query().queryMemberStatus().innerJoin(); // [何のためかコメント]
e.g. SetupSelectしたリレーションを内部結合に {MemberStatus} @DisplaySql
select dfloc.MEMBER_ID, dfloc.MEMBER_NAME, ...
     , dfrel_0.MEMBER_STATUS_CODE, ...
  from MEMBER dfloc
    inner join MEMBER_STATUS dfrel_0 on ...

メソッド仕様

リレーションに対してのみ利用

リレーションに対してのみ利用できます。基点テーブルの Query で呼び出した場合は例外です。

複数回の呼び出し

何度呼び出しても設定が上書きされるだけですが、業務的な意味はありません。

Union や SubQuery では

Union や SubQuery などで指定された同じリレーションには影響しません。 同じく内部結合にしたい場合は、それぞれ innerJoin() を呼び出す必要があります。

ネストしたリレーションでは

ネストしたリレーションに対して利用した場合でも、そのリレーションを辿る途中のリレーションには影響しません。 あくまでピンポイントで指定されたリレーションの結合だけが内部結合になります。 SQLの文法的には、その場合は途中のリレーションも内部結合にしてしまっても同じ結果となりますが、 この機能はあくまでピンポイントでの指定を基本としています。