[seasar-dotnet:1871] Re: [DBFlute.NET]業務的one-to-oneな条件に他テーブルのカラム値指定

fp [E-MAIL ADDRESS DELETED]
2010年 10月 12日 (火) 12:56:34 JST


fpです。

久保さん、こんにちは。

大いに活用します。ありがとうございます。

> $foreignTableの後ろのDISPLAY_ORDERをパースして
> 取り出して、インラインビューの select 句に指定しています。
> MEMBER_LOGINに同名のカラムがあるとだめですが、
> "select * " をするよりかは遥かにバッティングの可能性は減るかと。
> (オプションのような形式でエリアス名を指定する拡張を
> 後で入れようと思えば入れられるような構造になっています)

fixedCondition の OverRelation のカラムは on句の絞込み条件
での使用に限定されますから独自のエリアス名で補完すれば
バッティングもなくなりますね。

(2010/10/12 3:28), kubo wrote:
> 久保(jflute)です。
> 
> fpさん、お気遣いありがとうございます。
> まあ、業務的one-to-oneもこれだけ使われれば喜ぶと思うので。
> (他ではなかなか無いDBFluteらしい機能でもあるし)
> 
> そして、ひとまず Java の方では落ち着きました。
> LocalTable や ForeignTable を指定するときは、
> $localTable、$foreignTable というように定数指定にし、
> ReferrerTable の時だけテーブル名そのままにしました。
> (そうすることで、もっと曖昧さがなくなるかと)
> 
> ; FK_MEMBER_MEMBER_LOGIN_FOREIGN_FOREIGN_OVER_TEST = map:{
>      ; localTableName  = MEMBER    ; foreignTableName  = MEMBER_LOGIN
>      ; localColumnName = MEMBER_ID ; foreignColumnName = MEMBER_ID
>      ; fixedCondition =
>   $$over($localTable.memberStatus)$$.DISPLAY_ORDER
>          = $$over($foreignTable.memberStatus)$$.DISPLAY_ORDER
>      ; fixedSuffix = AsForeignForeignOverTest
> }
> 
> そして、$foreignTable を指定すると、
> 以下のようなSQLに自動解決されます。
> 
>    from member dflocal
>      left outer join member_status dfrelation_0 on
> dflocal.MEMBER_STATUS_CODE = dfrelation_0.MEMBER_STATUS_CODE
>      left outer join (select dffixedbase.*, dffixedjoin_0_0.DISPLAY_ORDER
>                         from member_login dffixedbase
>                           left outer join member_status dffixedjoin_0_0
> on dffixedbase.LOGIN_MEMBER_STATUS_CODE =
> dffixedjoin_0_0.MEMBER_STATUS_CODE
>                      ) dfrelation_4
>        on dflocal.MEMBER_ID = dfrelation_4.MEMBER_ID
>       and dfrelation_0.DISPLAY_ORDER = dfrelation_4.DISPLAY_ORDER
> 
> $foreignTableの後ろのDISPLAY_ORDERをパースして
> 取り出して、インラインビューの select 句に指定しています。
> MEMBER_LOGINに同名のカラムがあるとだめですが、
> "select * " をするよりかは遥かにバッティングの可能性は減るかと。
> (オプションのような形式でエリアス名を指定する拡張を
> 後で入れようと思えば入れられるような構造になっています)
> 
> 一旦、この段階でDBFlute.NETの方への移植をします。
> (結構、たくさん修正しているのである程度時間掛かります)
> 
> ちなみに、上記の $foreignTable のインラインビュー方式を
> fpさんの業務で活用することはできますでしょうか?
> 
> 2010/10/12 fp<[E-MAIL ADDRESS DELETED]>:
>> fpです。
>>
>> 久保さん、ありがとうございます。
>>
>> 無理のない範囲で宜しくお願いします。
>> (既に大抵無理言ってしまってますが)
>>
>> (2010/10/12 1:03), kubo wrote:
>>> 久保(jflute)です。
>>>
>>>> 私の想定するSQLは単純に以下の通りです。
>>>>
>>>> select ...
>>>>    from MEMBER dflocal
>>>>      left outer join MEMBER_LOGIN dfrelation_4
>>>>        on dflocal.MEMBER_ID = dfrelation_4.MEMBER_ID
>>>>      left outer join MEMBER_STATUS dfrelation_4_1
>>>>        on dfrelation_4.LOGIN_MEMBER_STATUS_CODE =
>>>> dfrelation_4_1.MEMBER_STATUS_CODE
>>>>       and dfrelation_4_1.DISPLAY_ORDER = 2
>>>
>>> なるほど、MEMBER_LOGIN の自体の on 句に入るのではなく、
>>> その先のMEMBER_STATUS の on 句に指定した条件を入れる
>>> イメージでしたか。で、そのように条件付けると、
>>> 業務的には MEMBER からone-to-oneになると。
>>>
>>> fixedConditionは、現状ではMEMBER_LOGIN の join の on 句の
>>> 条件を指定することが大前提となっていますので、その土台のまま
>>> ではそのようなSQLは作ることはできません。
>>> なので、実現するには MEMBER_STATUS の on 句の方に
>>> 指定できるような新しい仕組みが必要ですね。
>>> 考えられるのが以下のパターン:
>>>
>>> A. MEMBER_LOGIN の on 句に条件を入れるパターン(通常)
>>> B. MEMBER_STATUS の on 句に条件を入れるパターン(新)
>>> C. 両方の on 句に条件を入れるパターン(新)
>>> D. Cに加えて、さらに先の関連テーブルにも入れるパターン(新)
>>>
>>> fpさんの要件では B というところですね。
>>> これはこれで、ほぼ新機能と言っていいもので、
>>> 特に「dfpropでどう指定させるのか」を
>>> 時間掛けて練る必要がありそうです。
>>> (fixedConditionに加えてoverConditionという項目を追加とか、
>>> fixedConditionの中で自動判別させて条件の嫁ぎ先を決定するとか)
>>>
>>> とりあえずは一旦、上記以外のパターンの実装を固めて、
>>> SNAPSHOT 出したいと思います。上記以外のパターンだけでも
>>> 業務的one-to-oneがしっかりと使えるように。
>>> (どうしても Java to C# で、ちょっとC#版が遅れるので段階的に)
>>>
>>> また、ひとまず以下のようなSQLが自動解決できれば、
>>> それはそれで役に立ちそうなので、できるようにしてみようかと。
>>> (一応、B のパターンと同じ動作になり得るかなと)
>>>
>>> select *
>>>    from member dflocal
>>>      left outer join
>>>        (select MEMBER_LOGIN.*, dfrelation_4_1.DISPLAY_ORDER
>>>           from MEMBER_LOGIN
>>>           left outer join MEMBER_STATUS dfrelation_4_1
>>>             on MEMBER_LOGIN.LOGIN_MEMBER_STATUS_CODE =
>>> dfrelation_4_1.MEMBER_STATUS_CODE
>>>        ) dfrelation_4
>>>        on dflocal.MEMBER_ID = dfrelation_4.MEMBER_ID
>>>       and dfrelation_4.DISPLAY_ORDER = 2
>>>
>>> dfprop において、fixedConditionの中に
>>> $$over(!foreignTable!.memberStatus)$$.DISPLAY_ORDER
>>> というように指定があれば、InlineViewを自動で展開して、
>>> DISPLAY_ORDER だけを select 句に追加して、
>>> MEMBER_LOGINのエリアス名経由でDISPLAY_ORDERが
>>> 利用できるように。
>>> (って書いておいてできなかったりして...一応半分くらいできてて)
>>>
>>> 2010/10/11 fp<[E-MAIL ADDRESS DELETED]>:
>>>> fpです。
>>>>
>>>> 久保さん、こんばんは、ありがとうございます。
>>>>
>>>> 今まで良く分かっていなかったのですが、
>>>> このレスで何となく久保さんの仰る曖昧さの意味が
>>>> 分かったような気がします。
>>>> ほんと申し訳ありません。
>>>>
>>>> 「二つの left outer join が、互いに参照し合う」
>>>> というのが問題ですね。
>>>>
>>>> 私の想定するSQLは単純に以下の通りです。
>>>>
>>>> select ...
>>>>    from MEMBER dflocal
>>>>      left outer join MEMBER_LOGIN dfrelation_4
>>>>        on dflocal.MEMBER_ID = dfrelation_4.MEMBER_ID
>>>>      left outer join MEMBER_STATUS dfrelation_4_1
>>>>        on dfrelation_4.LOGIN_MEMBER_STATUS_CODE =
>>>> dfrelation_4_1.MEMBER_STATUS_CODE
>>>>       and dfrelation_4_1.DISPLAY_ORDER = 2
>>>>
>>>> イメージとしては、dfpropで
>>>> $$over($$foreignAlias$$.overRelationAlias)$$
>>>> と指定したら
>>>>
>>>> $$localAlias$$
>>>> left outer join
>>>> $$foreignAlias$$
>>>>    on $$localAlias$$.ID = $$foreignAlias$$.ID
>>>> left outer join
>>>> $$overRelationAlias$$
>>>>    on $$foreignAlias$$.overRelationAlias_ID = $$overRelationAlias$$.ID
>>>> and [fixedCondition]
>>>>
>>>> です。
>>>>
>>>> $$over($$localAlias$$.overRelationAlias)$$
>>>> なら
>>>>
>>>> $$localAlias$$
>>>> left outer join
>>>> $$foreignAlias$$
>>>>    on $$localAlias$$.ID = $$foreignAlias$$.ID
>>>> left outer join
>>>> $$overRelationAlias$$
>>>>    on $$localAlias$$.overRelationAlias_ID = $$overRelationAlias$$.ID
>>>> and [fixedCondition]
>>>>
>>>> で、
>>>> $$over(dflocal.overRelationAlias)$$
>>>> なら
>>>>
>>>> from dflocal
>>>> left outer join
>>>> $$localAlias$$
>>>>    on dflocal.localAlias_ID = $$localAlias$$.ID
>>>> left outer join
>>>> $$foreignAlias$$
>>>>    on $$localAlias$$.ID = $$foreignAlias$$.ID
>>>> left outer join
>>>> $$overRelationAlias$$
>>>>    on dflocal.overRelationAlias_ID = $$overRelationAlias$$.ID
>>>> and [fixedCondition]
>>>>
>>>> で、いけるのかなと。
>>>>
>>>> ※  [fixedCondition]は
>>>>      $$overRelationAlias$$.XxxColumn = $cls(XxxType.XxxCode)
>>>> とか
>>>>      $$foreignAlias$$.XxxColumn = $$overRelationAlias$$.XxxColumn
>>>> とか
>>>>      $$localAlias$$.XxxColumn<= $$overRelationAlias$$.XxxColumn
>>>> とか
>>>>      dflocal.XxxColumn>= $$overRelationAlias$$.XxxColumn
>>>> です。
>>>>
>>>> 長々とすみません。宜しくお願いします。
>>>>
>>>>
>>>> (2010/10/11 22:37), kubo wrote:
>>>>> 久保(jflute)です。
>>>>>
>>>>> fpさん、もうちょっとアドバイス頂ければと思います。
>>>>> 定義した業務的one-to-oneの foreignTable を経由した
>>>>> さらなる foreignTable のカラムを fixedCondition に
>>>>> 利用するパターンですが、二つの left outer join が、
>>>>> 互いに参照し合うのでSQL的に動作するのかどうか、
>>>>> ちょっと疑問に思っています。
>>>>>
>>>>> local = MEMBER
>>>>> foreign = MEMBER_LOGIN (業務的one-to-one)
>>>>> foreignのforeign = MEMBER_STATUS (LOGIN経由)
>>>>>
>>>>> select ...
>>>>>      from member dflocal
>>>>>        left outer join MEMBER_STATUS dfrelation_4_1
>>>>>          on dfrelation_4.LOGIN_MEMBER_STATUS_CODE =
>>>>> dfrelation_4_1.MEMBER_STATUS_CODE
>>>>>        left outer join MEMBER_LOGIN dfrelation_4
>>>>>          on dflocal.MEMBER_ID = dfrelation_4.MEMBER_ID
>>>>>         and dfrelation_4_1.DISPLAY_ORDER = 2
>>>>>
>>>>> だと、MEMBER_STATUS の left outer join が先に来て、
>>>>> dfrelation_4 が(まだ)解決できません。順番を逆にしても:
>>>>>
>>>>> select ...
>>>>>      from member dflocal
>>>>>        left outer join MEMBER_LOGIN dfrelation_4
>>>>>          on dflocal.MEMBER_ID = dfrelation_4.MEMBER_ID
>>>>>         and dfrelation_4_1.DISPLAY_ORDER = 2
>>>>>        left outer join MEMBER_STATUS dfrelation_4_1
>>>>>          on dfrelation_4.LOGIN_MEMBER_STATUS_CODE =
>>>>> dfrelation_4_1.MEMBER_STATUS_CODE
>>>>>
>>>>> 今度は、MEMBER_LOGIN の on 句で、
>>>>> dfrelation_4_1 が解決できません。
>>>>> MySQLとPostgreSQLで実際に試してエラーになりました。
>>>>>
>>>>> 頭の中でいけるかなぁと勝手に思っていはいたのですが、
>>>>> いざやってみると確かに...。
>>>>> ちょっと自分が勘違いしているかもしれません。
>>>>> fpさんのところで実業務で想定しているパターンを
>>>>> もう少し情報頂けないでしょうか?
>>>>> (どういうSQLを想定されていますでしょうか!?)
>>>>>
>>>>> #
>>>>> # 以下のようにすれば、いけそうですが、
>>>>> # 同名カラムをどう解決したものかってとこですね...
>>>>> #
>>>>>
>>>>> select *
>>>>>      from member dflocal
>>>>>        left outer join
>>>>>          (select *
>>>>>             from MEMBER_LOGIN
>>>>>             left outer join MEMBER_STATUS dfrelation_4_1
>>>>>               on MEMBER_LOGIN.LOGIN_MEMBER_STATUS_CODE =
>>>>> dfrelation_4_1.MEMBER_STATUS_CODE
>>>>>          ) dfrelation_4
>>>>>          on dflocal.MEMBER_ID = dfrelation_4.MEMBER_ID
>>>>>         and dfrelation_4.DISPLAY_ORDER = 2
>>>>>
>>>>>
>>>>> 2010/10/11 fp<[E-MAIL ADDRESS DELETED]>:
>>>>>> fpです。
>>>>>>
>>>>>> ありがとうございます。
>>>>>>
>>>>>> 申し訳ありませんが、宜しくお願いします。
>>>>>>
>>>>>> (2010/10/11 18:46), kubo wrote:
>>>>>>> 久保(jflute)です。
>>>>>>>
>>>>>>>> 当方のプロジェクトでは、話に出た全パターン当てはまります。
>>>>>>> なるほどー、じゃあ頑張りますよぅ。
>>>>>>> こっちも「すぐに使ってもらえないかもしれない機能」を
>>>>>>> 実装するのはリスクがあって、すぐに確認・実践してもらえる
>>>>>>> ことで、要件に合った仕様と品質を担保してから公開できるので。
>>>>>>> (なので、大分安定を重視する時期に来たDBFluteでは要件のない
>>>>>>> 機能はあえて実装せずに将来の機会を待つこともあります、
>>>>>>> 今回のパターンはそのつもりでした...)
>>>>>>> もちろん、実現コストに全て委ねられますが、あともうちょい頑張れば
>>>>>>> できそうなので。(フィルタ処理はコールバックで遅延させます)
>>>>>>>
>>>>>>> 2010/10/11 fp<[E-MAIL ADDRESS DELETED]>:
>>>>>>>> fpです。
>>>>>>>>
>>>>>>>> 久保さん、ありがとうございます。
>>>>>>>>
>>>>>>>> 当方のプロジェクトでは、話に出た全パターン当てはまります。
>>>>>>>>
>>>>>>>> ただ、無理なようでしたら機能制限の範囲内で回避策を
>>>>>>>> 考えますので、それほど緊急とはお考えにならないで下さい。
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> すれちがってしまいましたね。>[seasar-dotnet:1861]
>>>>>>>>
>>>>>>>>
>>>>>>>> (2010/10/11 18:26), kubo wrote:
>>>>>>>>> 久保(jflute)です。
>>>>>>>>>
>>>>>>>>> ああ、なるほど、業務的one-to-oneのリレーションを
>>>>>>>>> 通過した先の foreignTable のことですね。
>>>>>>>>> しかも、今の仕様だと辿るリレーションの中で、
>>>>>>>>> 業務的one-to-oneを含めることができないので、
>>>>>>>>> 参照元テーブルから辿ることもできないですね。
>>>>>>>>>
>>>>>>>>> 業務的one-to-oneの参照先テーブルだけは特別に、
>>>>>>>>> ポイントとして指定できる唯一の foreignTable、
>>>>>>>>> もしくは、リレーションで特別に辿れる業務的one-to-one
>>>>>>>>> というように扱えればってところですね。
>>>>>>>>>
>>>>>>>>> $$over(MEMBER_LOGIN.memberStatus)$$
>>>>>>>>>
>>>>>>>>>        もしくは
>>>>>>>>>
>>>>>>>>> $$over(MEMBER.memberLoginAsValid.memberStatus)$$
>>>>>>>>>
>>>>>>>>> 該当の業務的one-to-oneが確定していない時点で、その奥の
>>>>>>>>> リレーションを有効にしてエリアス名を取得できるかどうか、
>>>>>>>>> その辺が実現の鍵になるので、ちょっと考えますね。
>>>>>>>>> (場合に寄っては、置換処理をコールバックで遅延させて
>>>>>>>>> 実行させるなどの工夫が必要かも...)
>>>>>>>>>
>>>>>>>>> ちなみに、fp さんの業務の中で、このパターンに
>>>>>>>>> 当てはまるものがありますでしょうか?
>>>>>>>>>
>>>>>>>>> 2010/10/11 fp<[E-MAIL ADDRESS DELETED]>:
>>>>>>>>>> fpです。
>>>>>>>>>>
>>>>>>>>>> 「OverRelation」を使わずに以下のようにできることは
>>>>>>>>>> 認識しています。
>>>>>>>>>>
>>>>>>>>>> ; FK_MEMBER_MEMBER_LOGIN_AS_VALID = map:{
>>>>>>>>>>          ; localTableName  = MEMBER    ; foreignTableName  = MEMBER_LOGIN
>>>>>>>>>>          ; localColumnName = MEMBER_ID ; foreignColumnName = MEMBER_ID
>>>>>>>>>>          ; fixedCondition =
>>>>>>>>>>            exists(select 'TRUE' from MEMBER_STATUS st
>>>>>>>>>>                    where $$foreignAlias$$.LOGIN_MEMBER_STATUS_CODE =
>>>>>>>>>>                          st.MEMBER_STATUS_CODE
>>>>>>>>>>                      and st.DISPLAY_ORDER = 2)
>>>>>>>>>>          ; fixedSuffix = AsValid
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> (2010/10/11 16:44), fp wrote:
>>>>>>>>>>> fpです。
>>>>>>>>>>>
>>>>>>>>>>> 久保さん、即座の御返事ありがとうございます。
>>>>>>>>>>>
>>>>>>>>>>> ん〜、dbflute_exampledb にうまい例が見つからないのですが
>>>>>>>>>>> 仮に、MEMBER ->            MEMBER_LOGIN ->            MEMBER_STATUS で
>>>>>>>>>>> MEMBER_STATUS.DISPLAY_ORDER = 2 の条件で
>>>>>>>>>>> MEMBER ->            MEMBER_LOGIN に業務的one-to-oneなFKを設定できる
>>>>>>>>>>> とした場合、
>>>>>>>>>>>
>>>>>>>>>>> ; FK_MEMBER_MEMBER_LOGIN_AS_VALID = map:{
>>>>>>>>>>>           ; localTableName  = MEMBER    ; foreignTableName  = MEMBER_LOGIN
>>>>>>>>>>>           ; localColumnName = MEMBER_ID ; foreignColumnName = MEMBER_ID
>>>>>>>>>>>           ; fixedCondition =
>>>>>>>>>>>               $$over(MEMBER_LOGIN.memberStatus)$$.DISPLAY_ORDER = 2
>>>>>>>>>>>           ; fixedSuffix = AsValid
>>>>>>>>>>> }
>>>>>>>>>>> と書きたい、ということです。
>>>>>>>>>>> 定義上明示されている MEMBER_LOGIN をポイントテーブルと
>>>>>>>>>>> することに曖昧さがあるとは思わないのですが。
>>>>>>>>>>>
>>>>>>>>>>> いままさに定義しようとしているリレーションのための
>>>>>>>>>>> 条件の指定に、以下は適用できませんし。
>>>>>>>>>>>> MEMBER.memberStatusByFooCode というように、
>>>>>>>>>>>> 明示的にリレーションを書いてもらう仕様にしています。
>>>>>>>>>>>
>>>>>>>>>>> foreignTable についての認識に齟齬があるのでしょうか?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> (2010/10/11 15:56), kubo wrote:
>>>>>>>>>>>> 久保(jflute)です。
>>>>>>>>>>>>
>>>>>>>>>>>>> とはいえ、foreignTable をポイントとすることはできないでしょうか?
>>>>>>>>>>>>
>>>>>>>>>>>> 例えば、会員に会員ステータスへのFKカラムが二つあった場合、
>>>>>>>>>>>> ポイントを会員ステータスにするとになります。
>>>>>>>>>>>> なので、foreignTableに関しては、
>>>>>>>>>>>> MEMBER.memberStatusByFooCode というように、
>>>>>>>>>>>> 明示的にリレーションを書いてもらう仕様にしています。
>>>>>>>>>>>> 親の親の親の親の親のカラムとかになると、指定が長くて
>>>>>>>>>>>> 大変ですが、曖昧さの可能性も増えるので、
>>>>>>>>>>>> そこの優先度を練り直したって感じです。
>>>>>>>>>>>>
>>>>>>>>>>>>>> ポイントテーブルは ORDER_ITEM で、リレーションは order。
>>>>>>>>>>>>>>          ->               $$over(ORDER_ITEM.order)$$
>>>>>>>>>>>>>
>>>>>>>>>>>>> これは実際の構成ではなく、あくまで例ってことで (^^;
>>>>>>>>>>>>
>>>>>>>>>>>> おっと、そうでしたかぁ、失敬w
>>>>>>>>>> _______________________________________________
>>>>>>>>>> seasar-dotnet mailing list
>>>>>>>>>> [E-MAIL ADDRESS DELETED]
>>>>>>>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> seasar-dotnet mailing list
>>>>>>>>> [E-MAIL ADDRESS DELETED]
>>>>>>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> seasar-dotnet mailing list
>>>>>>>> [E-MAIL ADDRESS DELETED]
>>>>>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> seasar-dotnet mailing list
>>>>>>> [E-MAIL ADDRESS DELETED]
>>>>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>>>
>>>>>> _______________________________________________
>>>>>> seasar-dotnet mailing list
>>>>>> [E-MAIL ADDRESS DELETED]
>>>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>>>
>>>>> _______________________________________________
>>>>> seasar-dotnet mailing list
>>>>> [E-MAIL ADDRESS DELETED]
>>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>
>>>> _______________________________________________
>>>> seasar-dotnet mailing list
>>>> [E-MAIL ADDRESS DELETED]
>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>
>>> _______________________________________________
>>> seasar-dotnet mailing list
>>> [E-MAIL ADDRESS DELETED]
>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>
>> _______________________________________________
>> seasar-dotnet mailing list
>> [E-MAIL ADDRESS DELETED]
>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>
> _______________________________________________
> seasar-dotnet mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-dotnet



seasar-dotnet メーリングリストの案内