(Query)DerivedReferrer

概要

基本概念

子テーブルの導出カラム(最大値や合計値)で絞り込みます。(Specify)DerivedReferrer が "取得" であるのに対して、これは "絞り込み" です。

例えば、"購入金額合計が10000円を超えている会員" というように、 子テーブルのカラムの値を元に導出したカラムで、絞り込み条件を設定することができます。 where 句の相関サブクエリを使って条件を設定します。

会話上では、くえりでぃらいゔどりふぁらぁ と表現します。単に でぃらいゔどりふぁらぁ と言った場合、厳密には (Query)DerivedReferrer を含みますが、前後関係で分かる場合は、(Specify)DerivedReferrer の方を示すことが多いです。

取得と絞り込みで違う機能

導出カラムの取得と絞り込みで違う機能になっています。 ConditionBeanのポリシーがそういった傾向があるのでわかりやすいと思われますが、そのポリシーだけでなく、SQLでは select 句にて導出した値を where 句で取り扱うことができません(order by では扱える)。インラインビューという手もありますが、取得と絞り込みで微妙に条件が変わる可能性も考慮して、このような仕様となっています。

実装方法

実装の流れ

query() の後、derived[referrer-table]List() を呼び出し、その後、max() や sum() など関数メソッドを選び、SubQuery のコールバック実装を引数に指定します。オーバーロードの第二引数は、様々なオプション(coalesce 関数の利用など)を指定する DerivedReferrerOption を指定します。コールバックの中では、SpecifyColumn を使って導出カラムを(一つ)指定します。

e.g. (Query)DerivedReferrerの実装手順 (Eclipseでコード補完) {MEMBER, MEMBER_LOGIN} @Java
MemberCB cb = new MemberCB();
cb.q // .q と打って enter
--
cb.query()
--
// 1. .d まで打つと関連テーブル選択
// 2. PL (PurchaseList) で enter
cb.query().dPL
--

cb.query().derivedPurchaseList()
--

// max() や min()、sum() などの関数メソッドを選んで enter
//  => max(), min(), sum(), avg(), count(), countDistinct()
// それぞれに、オーバーロードで DerivedReferrerOption が指定できる
//  => 導出値が null の可能性がある場合のために、coalesce 関数も利用できる
cb.query().derivedPurchaseList().su
--

// メソッドが補完されて、引数の "subQuery" が選択状態に
cb.query().derivedPurchaseList().sum(subQuery)
--

// "new " (new + 空白一つ) と打って ctrl + space そして enter
cb.query().derivedPurchaseList().sum(new )
--

// 実装メソッドの空実装が自動生成される (Eclipse-3.5 以上)
cb.query().derivedPurchaseList().sum(new SubQuery<PurchaseCB>() {
    
    public void query(PurchaseCB subCB) {
        // TODO Auto-generated method stub
        
    }
})
--

// ctrl (or command) + D で不要な空行やTODOコメントを消して
// サブクエリ(子テーブル)の導出カラムと絞り込み条件を指定
cb.query().derivedPurchaseList().max(new SubQuery<PurchaseCB>() {
    public void query(PurchaseCB subCB) {
        subCB.specify().columnPurchasePrice(); // 導出カラムの指定
        subCB.query().setPaymentCompleteFlg_Equal_True(); // 絞り込み条件
    }
}).greE // 続けて比較条件を指定、ここでは .greE (GreaterEqual)
--

cb.query().derivedPurchaseList().max(new SubQuery<PurchaseCB>() {
    public void query(PurchaseCB subCB) {
        subCB.specify().columnPurchasePrice(); // 導出カラムの指定
        subCB.query().setPaymentCompleteFlg_Equal_True(); // 絞り込み条件
    }
}).greaterEqual(10000) // 引数に条件値を設定

SQL上では、FKを構成する関連カラムを使った相関条件が自動的に付与されます。

e.g. (Query)DerivedReferrerを使って(支払済み)最大購入価格が10000円以上の会員を取得 @DisplaySql
...
  from MEMBER dfloc
 where (select sum(sub1loc.PURCHASE_PRICE)
          from PURCHASE sub1loc
         where sub1loc.MEMBER_ID = dfloc.MEMBER_ID
           and sub1loc.PAYMENT_COMPLETE_FLG = 1
       ) >= 10000
...

適切な比較条件、および、関数を選んで実装して下さい。関数によっては利用できるカラムのデータ型が限定されるものもあります。

関連テーブルへのアプローチ

関連テーブルへのアプローチは、(Specify)DerivedReferrer と同じです。

子テーブルの子テーブル(one-to-many-to-many)に関しては、(Query)DerivedReferrer の中で (Specify)DerivedReferrer を利用する、という形式になります。(@since 0.9.7.7)

導出値をSQL関数でフィルタ

(Specify)DerivedReferrer と同じです。

(導出カラムの)取得の場合は、取得した後にアプリ側でハンドリングできますが、 絞り込みの場合は、導出値はSQLの中で完結しますので、(Query)DerivedReferrer の方がフィルタが必要になる場面は多いと想定されます。 特に、導出値が null になる可能性は多くの場合で想定されますので(紐づく子テーブルがデータが一件も無く、max() や sum() を使う場合など)、coalesce を利用する場面は多いでしょう。

メソッド仕様

基本仕様

引数の指定
引数の SubQuery、条件値(isNull, isNotNull は除く)は必須です。DerivedReferrerOption もオーバーロードのメソッドを指定している場合は必須です。
導出カラムの指定は一つ
導出カラムの指定は必ず一つだけです。指定が無い場合、指定があり過ぎる場合は例外です。
サブクエリのConditionBean
サブクエリの ConditionBean は、導出カラムと絞り込み条件だけの指定に利用するものです。 SetupSelect や OrderBy などサブクエリとして必要のない機能は呼び出してはいけません。

利用できる関数

利用できる関数は、(Specify)DerivedReferrer と同じです。

(Specify)DerivedReferrer - 利用できる関数

利用できる比較条件

利用できる比較条件は、以下の通りです。

equal()
等値
greaterThan()
大なり
lessThan()
小なり
greaterEqual()
大なりイコール
lessEqual()
小なりイコール
isNull()
null かどうか
isNotNull()
null でないかどうか
between()
小なりイコール、かつ、大なりイコール @since 0.9.9.2F

引数の条件値の型は Object 型です。カラムの型に合わせたプログラム型の値を指定して下さい。

サポートされる関連テーブル

Referrer と定義付けられる one-to-many の関連に対してサポートされます。また、基点テーブルが単一の主キーである必要があります。(複合主キーはNG)