14 返信 最新の回答 日時: Aug 27, 2009 4:21 PM ユーザー:d.o

    正規化されたDBから表形式にするには?

    d.o

      タイトル

      正規化されたDBから表形式にするには?

      フォーラムに投稿

      みなさんこんにちは

       

      分かりにくいタイトルですみません。

       

      たとえば...テストの点数のような情報があったとします

       

      氏名 国語 数学 英語 社会 理科

      安藤 30 40 50 60

      佐藤 20 60 80    80

      鈴木 40 20 50 50

       


      理科と社会は選択科目なので空欄があります。また、見出し(国語、数学...)の部分は学年やクラスによって科目数や内容が変わるとします。カリキュラムが変わったりすると..まったく別のものになることもあります。

       

      さて、こういう 情報をDB化するなら、正規化して下のようにしますよね?

       

      氏名 科目名 得点

      安藤 国語  30

      安藤 数学  40

      安藤 英語  50

      安藤 社会  60

      佐藤 国語  20

      佐藤 数学  60

      佐藤 英語  80

      佐藤 理科  80

      鈴木 国語  40

      鈴木 数学  20

      鈴木 英語  50

      鈴木 社会  50

       

      (氏名は同姓同名の可能性があるので本当はキーに適さないですよね。実際には学生番号等のユニークな値をキーにするとは思います) 

      こうしておけばテストを受けている科目が人によって違っても問題ありませんし、 カリキュラムが変わって科目の名称が変わっても問題無いと思います。

      さてさて、問題はこのように正規化されたDBから元の一覧表のように表示・印刷させるにはどうしたら良いかということです。

       

      印刷用に一時的に使用するテーブルを作って、そこへインプットというのも考えたのですが...。もっとスマートな方法はないものでしょうか?

      よろしくお願いします。 

        • 1. Re: 正規化されたDBから表形式にするには?
          Hiro
            

           環境をお知らせください。

          お求めのことはクロス集計といいます。

          割とポピュラーなお題で、取り合えず以下のBBSあたりを検索すると過去ログに解説やサンプルがあると思います。

           http://www.russ.jp/stepbbs/step.cgi?

           http://www.kipwmi.com/fmbbs/wwwlng.cgi

          • 2. Re: 正規化されたDBから表形式にするには?
            d.o
              

            Hiroさん

            レスありがとうございます。

             

            >環境をお知らせください

            失礼しました。うっかり書き忘れました。

            環境はMac、Windows混在でFilemaker9と10も混在してます。 

            Filemaker server10上でデータベースを共有しています。

             

             

            • 3. Re: 正規化されたDBから表形式にするには?
              Hiro
                

              文章力がないもので解説代わりのサンプルを作りアップしておきました。

                http://briefcase.yahoo.co.jp/bc/brghspr/lst?&.dir=/352b/fcb8&.src=bc&.view=l

              宜しかったらご参考ください。「クロス集計.zip」名のファイルです。

               

              サンプルの方法は、設定が多少面倒ですが一度設定してしまえば後は自動更新で楽だと思います。

              • 4. Re: 正規化されたDBから表形式にするには?
                user6776
                  

                すいません。FileMakerのフォーラムでこういう解決策を書き込むのは躊躇するのですが、、

                 

                Excelのピボットという機能を使ってはだめですかね?

                印刷だけするならこの方法が簡単かなぁと・・・。

                 

                それをご存知の上でFileMakerでやらなければならない理由があったならば、申し訳ないです。すいません。

                • 5. Re: 正規化されたDBから表形式にするには?
                  d.o
                    

                  Hiroさん

                  サンプルありがとうございます。

                   

                  いま、中身をみているのですが...結構複雑で理解するのに苦労しているところです。

                   

                  おもに以下の2つに集約出来るのかな?

                  ・集計する項目のリストを値一覧で作る→リストの値を繰り返しフィールドに展開→自己リレーションで得点のリストを取得して繰り返しフィールドに展開 

                   

                  ・氏名のリストを基にレコードIDをリストアップして自己リレーション→一人当たり一行で表示

                   

                  まだ細かいところは理解できていません。

                  もう少し勉強してみるつもりです。

                  ありがとうございました。 

                  • 6. Re: 正規化されたDBから表形式にするには?
                    d.o
                      

                    sago350さん

                     

                    レスありがとうございます。 

                     

                    ご指摘の通り、Excelを使えば簡単なのですが...自分一人が使うのではなく共有データベースのために考えています。

                    かろうじて入力作業は出来る程度のユーザーもいるのでエクスポートしたデータをExcelで..という方法は無理なんです。

                     

                    Excelのマクロを作っておいてエクスポートしたデータを読み込ませる...みたいなことをすればFilemakerからボタン一つで出来るのかもしれませんが..。

                     

                     

                     

                    • 7. Re: 正規化されたDBから表形式にするには?
                      d.o
                        

                      Hiroさん

                       

                      いただいたサンプルの中身をみて考えているのですが、ちょっとわからないところがあります。

                      もしよろしかったら補足説明をお願い出来ないでしょうか?変なお願いですみません。

                       

                      「得点一覧」 という計算フィールドの中身(計算式)がわからずにつっかえています。

                      ここさえクリア出来れば理解出来そうなのですが... 

                       

                      Let([

                      $一覧=Extend(get得点一覧);

                      $件数=ValueCount($一覧);

                      $回数=0;

                      $結果="";

                      $再帰式="Case(

                      not isEmpty($結果) or $回数≥$件数; $結果;

                      Let([$回数=$回数+1; $項目=Substitute(GetValue($一覧;$回数);\"|\";\"\¶\"); $科目=GetValue($項目;1); $得点=GetValue($項目;2); $結果=Case($科目=科目一覧; $得点)]; Evaluate($再帰式))

                      )"

                      ];

                      Evaluate($再帰式)

                      )

                       

                      お時間があればで結構です。よろしくお願いします。

                       

                      サンプルファイルの方法はリレーションもシンプルだし是非理解したいと思っています。

                       

                      • 8. Re: 正規化されたDBから表形式にするには?
                        Hiro
                          

                        > 「得点一覧」 という計算フィールドの中身(計算式)がわからずにつっかえています。

                        少し分り難い式を使いご免なさい。

                        いま目的は、

                          値一覧から検索キーを含む行を取出して そのまた行内から必要な値を得る、

                        ことなわけですが、

                        この方法として、

                         ・ループ・スクリプト

                         ・計算式

                        などが考えられると思います。ここで、

                         スクリプトは、ループを使うと考え方は単純化できますが手動操作となり自動更新できない、

                         計算式は、自動計算自動更新可能ですが、テキスト関数を駆使した複雑な式となる、

                        など一長一短があります。

                        そこで、 両者の良いとこ取りで、計算式でループ処理可能な「再帰計算式」を使いました。

                         

                        通常、 再帰計算はFMAdvanced版専用機能のカスタム関数だけを考えますが、

                        実はFMPの標準関数でも定義可能(最大ループ回数は300回前後相当のメモリー許容内ですが)です。

                        今回は標準関数による再帰式を採用して標準FMPに実装可能にしています。

                         

                        式内で再帰的に使われる引数はすべて事前にLet関数で変数化します。

                        再帰式自体も変数にして、式をテキストとして記述、再帰式を定義します。

                        最後に「テキスト記述式」 をEvaluate("テキスト式")で計算実行して計算結果をえます。

                         

                        式の構成は、

                        Let([

                        //▼式に必要な引数、変数、などを$変数定義

                        $引数=○○; $変数=□□;

                        //▼再帰式をテキストで定義

                        $再帰式=”テキスト式”

                        ];

                        //▼最後に上で定義した$再帰式を実行

                        Evaluate($再帰式)

                        )

                         

                        $再帰式=”テキスト式”の内容は、

                        Case(

                        再帰終了条件式; (ハイなら)現在の$結果で終了;

                        (イイエなら) Let関数で$変数や$結果へ必要な更新を行った後 Evaluate($再帰式)で式を再帰ループさせます。

                        )

                         

                        以上です。ご理解のお役に立ちますでしょうか。

                        にHiroにより編集されたメッセージ
                        • 9. Re: 正規化されたDBから表形式にするには?
                          shin
                            

                          Hiroさんと、少し違う手法で、集計してみました。

                          繰り返しフィールドを使ったテーブル内の簡単な計算と、集計機能を使っています。

                          項目の順番を変えるには、g_科目 というフィールドの科目名を変更してみて下さい。

                           

                          http://homepage.mac.com/hiramatsu/.Public/FileMaker/FMTips/fmijp/fmijp879.fp7.zip

                          • 10. Re: 正規化されたDBから表形式にするには?
                            Hiro
                              

                            もし再帰式が理解し辛いようでしたら、以下のより簡潔な一般関数式でも計算可能です。

                             

                            Case( PatternCount(Extend(get得点一覧);科目一覧)=0; "";


                            Evaluate("Left(\"" & Substitute(Extend(get得点一覧);[科目一覧 & "|";"\";0) & \""];["|" & 科目一覧;"\" & Left(\""]) & "\";0)")


                            )

                             

                            この場合、get得点一覧の内容を「科目|得点|科目」書式のリストが取得されるように修正して、

                            例えば、get得点一覧=
                              国語|30|国語
                              数学|40|数学
                              英語|50|英語

                              社会|60|社会

                            のような書式リストで、 科目一覧の計算繰り返し位置の値が「数学」とした時、

                            上記式の計算結果値は

                             式 → Left("国語|30|国語¶";0) & "40" & Left("¶英語|50|英語¶社会|60|社会";0) → 40


                            • 11. Re: 正規化されたDBから表形式にするには?
                              d.o
                                

                              Hiroさん

                               

                              解説ありがとうございます。

                              なんとか再帰式を理解することが出来ました!

                               

                              Filemakerの関数で再帰が出来るとは知りませんでした。

                               

                              いままでLet関数等も使っていなかったので理解に時間がかかってしまいました。

                               

                              いろいろと勉強になりました。解答をいただいただけでなくいろいろ勉強できたので大変うれしく思っています。

                              ありがとうございました。

                               

                              ところで、恥のかきついでというか..本論からそれる質問をさせていただけますか?

                              get科目一覧フィールド、get得点一覧フィールド 、getユニークRecID一覧フィールドでは

                              計算式として

                              Evaluate("ValueListItems(Get(ファイル名); \"科目一覧\" )"; 科目名)

                              のようにEvaluate関数を使用されていますよね。

                              ここでEvaluate関数を使用する理由を教えていただけますか?

                              単に

                              ValueListItems(Get(ファイル名); "科目一覧" )

                              でも機能はすると思いますが、Evaluateを使うメリットはどの部分でしょうか?

                               

                              おそらく基本的なことなのでしょうがEvaluate関数も使ったことが無かったもので。

                              よろしくお願いします。 

                              • 12. Re: 正規化されたDBから表形式にするには?
                                d.o
                                  

                                MrShinさん

                                 

                                サンプル拝見いたしました。

                                確かに簡単な方法ですね。

                                Hiroさんに教えていただいた方法と合わせると自分の用途に合いそうです。これからいろいろと自分なりに試してみたいと思います。

                                わざわざサンプルも作っていただきありがとうございます。 

                                • 13. Re: 正規化されたDBから表形式にするには?
                                  Hiro
                                    

                                  > ここでEvaluate関数を使用する理由を教えていただけますか?

                                   

                                  サンプルは勢いで書いたので、余り検証とかバグフィックスなどしてませんが 、

                                  多分、ページを再表示すること無く、編集結果を即時反映・自動表示更新するためのアイデア、だったかな?

                                  補足の親切仕様なので、もし必要なければ取り外しても機能上問題ありません。

                                  • 14. Re: 正規化されたDBから表形式にするには?
                                    d.o
                                      

                                    >多分、ページを再表示すること無く、編集結果を即時反映・自動表示更新するためのアイデア、だったかな?

                                    なるほど。そういうことでしたか。

                                     

                                    これはこれで別の場面でも使えそうな知識なので覚えておきたいと思います。

                                     

                                    何度も解答頂ありがとうございました。