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

kubo [E-MAIL ADDRESS DELETED]
2010年 10月 12日 (火) 01:03:21 JST


久保(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 メーリングリストの案内