(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 と同じです。
利用できる比較条件
利用できる比較条件は、以下の通りです。
- equal()
- 等値
- greaterThan()
- 大なり
- lessThan()
- 小なり
- greaterEqual()
- 大なりイコール
- lessEqual()
- 小なりイコール
- isNull()
- null かどうか
- isNotNull()
- null でないかどうか
- between()
- 小なりイコール、かつ、大なりイコール @since 0.9.9.2F
引数の条件値の型は Object 型です。カラムの型に合わせたプログラム型の値を指定して下さい。
サポートされる関連テーブル
Referrer と定義付けられる one-to-many の関連に対してサポートされます。また、基点テーブルが単一の主キーである必要があります。(複合主キーはNg)