selectScalar(cb)
概要
基本概念
ConditionBeanをもとにスカラ検索 をします。
例えば、"一番若い会員の生年月日"、"全体の購入価格の平均" など、あるカラムの導出値を ConditionBean の絞り込み条件をもとに取得することができます。
スカラ値の取得ではなく、スカラ値を使ってSQL内で絞り込み条件をする、というような場合は、ScalarCondition という別の機能になります。(取得ではなく単なる絞り込み条件なので)
会話上では、せれくとすから と表現します。
実装方法
実装の流れ ※1.1.x (Java8版)
Behaviorの selectScalar() を呼び出し、受け取るスカラ値のプログラム型を引数に指定します。続けて、関数メソッドを呼び出し、ConditionBean で絞り込みを指定するコールバックを引数に指定します。
e.g. scalarSelect()の実装手順 (Eclipseでコード補完) {MEMBER} @Java
memberBhv.selSca // .selSca と打って enter
--
memberBhv.selectScalar(resultType);
--
// 引数に受け取るスカラ値のプログラム型を指定し、
// max() や min()、sum() などの関数メソッドを選んで enter
// => max(), min(), sum(), avg()
memberBhv.selectScalar(LocalDate.class).ma
--
// メソッドが補完されて、引数の "cbLambda" が選択状態に
memberBhv.scalarSelect(LocalDate.class).max(cbLambda)
--
// cbLambdaの部分で、_ll (補完テンプレートが有効なら)
memberBhv.selectScalar(LocalDate.class).max(_ll)
--
// Lambda引数名はcbにして...
// ScalarQuery のConditionBeanで導出カラムと絞り込み条件を指定
memberBhv.selectScalar(LocalDate.class).max(cb -> {
cb.specify().columnBirthdate(); // 生年月日の最大値
cb.query().setMemberStatusCode_Equal_Formalized(); // 正式会員に限る
})
--
memberBhv.selectScalar(LocalDate.class).max(cb -> {
cb.specify().columnBirthdate();
cb.query().setMemberStatusCode_Equal_Formalized();
}); // セミコロン ';' を打って ctrl(or command) + 2 そして L
--
// どん!
// (もしくは、ifPresent()やalwaysPresent()を使って、チェーンで戻り値を扱うでもOK)
OptionalScalar<LocalDate> maxDate = memberBhv.selectScalar(LocalDate.class).max(cb -> {
cb.specify().columnBirthdate();
cb.query().setMemberStatusCode_Equal_Formalized();
});
e.g. 正式会員における、生年月日の最大値を取得 @DisplaySql
select max(dfloc.BIRTHDATE) as dfscalar
from MEMBER dfloc
where dfloc.MEMBER_STATUS_CODE = 'FML'
実装の流れ ※1.0.x (Java6版)
Behaviorの scalarSelect() を呼び出し、受け取るスカラ値のプログラム型を引数に指定します。続けて、関数メソッドを呼び出し、ConditionBean で絞り込みを指定するコールバックを引数に指定します。
※DBFlute-1.1より、selectScalar() という名前になっています。
e.g. scalarSelect()の実装手順 (Eclipseでコード補完) {MEMBER} @Java
memberBhv.sc // .sc と打って enter
--
memberBhv.scalarSelect(resultType);
--
// 引数に受け取るスカラ値のプログラム型を指定し、
// max() や min()、sum() などの関数メソッドを選んで enter
// => max(), min(), sum(), avg()
memberBhv.scalarSelect(Date.class).ma
--
// メソッドが補完されて、引数の "scalarQuery" が選択状態に
memberBhv.scalarSelect(Date.class).max(scalarQuery)
--
// "new " (new + 空白一つ) と打って ctrl + space そして enter
memberBhv.scalarSelect(Date.class).max(new )
--
// 実装メソッドの空実装が自動生成される (Eclipse-3.5 以上)
memberBhv.scalarSelect(Date.class).max(new ScalarQuery<MemberCB>() {
public void query(MemberCB cb) {
// TODO Auto-generated method stub
}
})
--
// ctrl (or command) + D で不要な空行やTODOコメントを消して
// ScalarQuery のConditionBeanで導出カラムと絞り込み条件を指定
memberBhv.scalarSelect(Date.class).max(new ScalarQuery<MemberCB>() {
public void query(MemberCB cb) {
cb.specify().columnBirthdate(); // 生年月日の最大値
cb.query().setMemberStatusCode_Equal_Formalized(); // 正式会員に限る
}
}); // セミコロン ';' を打って ctrl(or command) + 2 そして L
--
LocalDate max = memberBhv.scalarSelect(LocalDate.class).max(new ScalarQuery<MemberCB>() {
public void query(MemberCB cb) {
cb.specify().columnBirthdate(); // 生年月日の最大値
cb.query().setMemberStatusCode_Equal_Formalized(); // 正式会員に限る
}
});
e.g. 正式会員における、生年月日の最大値を取得 @DisplaySql
select max(dfloc.BIRTHDATE) as dfscalar
from MEMBER dfloc
where dfloc.MEMBER_STATUS_CODE = 'FML'
子テーブルの導出カラム
導出カラムとして、子テーブルの導出カラムを指定することもできます。 ScalarSelect の中で (Specify)DerivedReferrer を利用します。(@since 0.9.7.7)
e.g. それぞれの会員の平均購入価格の会員全体での最大 @Java
OptionalScalar<Integer> maxAvg = memberBhv.scalarSelect(Integer.class).max(cb -> {
cb.specify().derivedPurchaseList().avg(purchaseCB -> {
purchaseCB.specify().columnPurchasePrice();
}, null);
cb.query().set...
});
e.g. それぞれの会員の平均購入価格の会員全体での最大 @DisplaySql
select max((select avg(sub1loc.PURCHASE_PRICE)
from PURCHASE sub1loc
where sub1loc.MEMBER_ID = dfloc.MEMBER_ID
)) as dfscalar
from MEMBER dfloc
where ...
導出値をSQL関数でフィルタ
導出値をSQL関数でフィルタすることができます。関数メソッドのオーバーロードの第二引数である ScalarSelectOption にて、そのフィルタ処理を指定することができます。@since 0.9.8.4
e.g. 集計対象レコードが一件も存在しなかった場合に null ではなく 0 を戻す @Java
Integer maxValue = memberBhv.scalarSelect(Integer.class).max(cb -> {
cb.specify().columnMemberId();
}, op -> op.coalesce(0));
もろもろの仕様は DerivedReferrer における DerivedReferrerOption と基本的に同じです。
メソッド仕様
引数
スカラ値のプログラム型、および、サブクエリは必須です。
戻り値
OptionalScalar型です。
検索結果が一件もない場合は、(DBMSの関数の仕様に従って) Optional が empty になることがあります。 coalesce()関数などを使うことで、nullがなくなるようにすることもできます。
導出カラムの指定
ScalarQuery 内での導出カラムは、必ず一つだけ指定します。 また、基点テーブルのカラム、もしくは、子テーブルの導出カラムのどちらかに限ります。 (カラム指定がない、もしくは、二つ以上のカラムが指定された場合は例外)
利用できる関数
利用できる関数は以下の通りです。
- max()
- 最大値。計算対象データが無い場合は null となる。
- min()
- 最小値。計算対象データが無い場合は null となる。
- sum()
- 合計値。数値のみ。計算対象データが無い場合は null となる。 受け取るプロパティの型がカラムに対応する型だと、(合計値なので)オーバーフローする可能性もあるので、業務的な可能性を踏まえてサイズの大きい型(Long や BigDecimal など)を利用すると良い。
- avg()
- 平均値。数値のみ。計算対象データが無い場合は null となる。値が小数点になる可能性があるので、受け取るプロパティの型を小数点を扱える型(BigDecimal など)にすると良い。
- count()
- レコード数。数値のみ。計算対象データが無い場合は 0 となる。selectCount(cb) と同じである。
- countDistinct()
- 種類数。数値のみ。計算対象データが無い場合は 0 となる。
ConditionBeanは絞り込み条件のみ
ScalarQuery の ConditionBean は、絞り込み条件だけの指定に利用するものです。 SetupSelect や OrderBy など絞り込み条件とは関係のない機能は呼び出してはいけません。
オーバーライド
selectList() と同じような要領となります。
UnionQuery での select 句のカラム
PKが存在するテーブルの場合で、引数の ConditionBean で UnionQuery を利用すると、UnionQuery に対応する select 句は PK カラムと導出カラムのみ列挙されます。 つまり、CLOB や TEXT 型のカラムが含まれるテーブルで、union の distinct 処理でそれらカラムがサポートされない DBMS でも問題なく UnionQuery を利用することができます(@since 0.9.7.7)。
旧バージョン、および、PKなしテーブル(ビューも含む)では、バージョンに関わらず回避はできません。ビューにおいては、AdditionalPrimaryKey で疑似の PK を設定すると良いでしょう。