2

「単純な」家系図を必要とするアプリケーションがあります。家族のメンバーから1つのIDを指定して、家族全体のデータを取得するクエリを実行できるようにしたいと思います。養子縁組やその他の曖昧さを考慮する必要がないので、私は単純だと言います。アプリケーションの要件は次のとおりです。

  • 同じ遺伝子系統の2人は繁殖できません
  • 新しい家系の追加を許可する必要がある(以前の家族がいない新しい人)
  • クエリを介して兄弟、親を個別にプルできる必要があります

データベースの適切な構造を考え出すのに問題があります。これまでに2つの解決策を考え出しましたが、それらはあまり信頼性が低く、おそらくすぐに手に負えなくなるでしょう。

解決策1では、family_idsフィールドをpeopleテーブルに配置し、一意のファミリIDのリストを保存します。2人が繁殖するたびに、リストは互いにチェックされ、IDが一致しないことを確認します。すべてがチェックアウトされると、2つのリストがマージされ、子のfamily_idsフィールドとして設定されます。

例:

Father (family_ids: (null)) breeds with Mother (family_ids: (213, 519)) ->
Child (family_ids: (213, 519)) breeds with Random Person (family_ids: (813, 712, 122, 767)) ->
Grandchild (family_ids: (213, 519, 813, 712, 122, 767))

などなど...これで私が目にする問題は、時間が経つにつれてリストが不当に大きくなることです。

ソリューション2は、cakephpの関連付けを使用して次のことを宣言します。

public $belongsTo = array(
    'Father' => array(
        'className' => 'User',
        'foreignKey' => 'father_id'
    ),
    'Mother' => array(
        'className' => 'User',
        'foreignKey' => 'mother_id'
    )
);

ここで、recursiveを2に設定すると、母親と父親の結果、母親と父親の結果などが取得されます。このルートの問題は、データがネストされた配列にあり、コードを効率的に処理する方法がわからないことです。

誰かが私が達成したいことを処理するための最も効率的な方法の方向に私を導くことができれば、それは非常に役に立ちます。どんな助けでも大歓迎です、そして、私は誰でも持っているどんな質問にも喜んで答えます。どうもありがとう。

4

1 に答える 1

2

SQL (より正確には RDBS) では、次のソリューションを使用します。

people1)次のフィールドを持つテーブルを作成します- id、、、、。最初のものは典型的な主キー列です。father_id と Mother_id はこの列を参照しますが、NULL 可能です (新しい家系を追加できるようにするため)。namefather_idmother_id

2)relatives次のフィールドを持つテーブルを作成します - person_id, ancestor_id. どちらも NULL ではなく、どちらも複合主キーを形成し、どちらも の FK ですperson.id

以上です。いいえ、本当に!) 次に、タスクを検討します。

  • 家系のない人を数人追加

それもかなり実行可能です: INSERT INTO people (name) VALUES ('some_name'). 秘訣は、この新鮮な人に関連する別の挿入を親戚に作成することです。 INSERT INTO relatives VALUES (%new_person_id%, %new_person_id%)

それは何のためですか?最も一般的なタスクを考えてみましょう: 実際に父親と母親の両方が既にテーブルにリストされている人物を追加します。この構造を使用すると、(対応するレコードを に挿入し、結果としてpeopleこれを取得した後)...と同じくらい簡単に実行できます...person_id

INSERT INTO relatives 
    SELECT %new_person_id%, ancestor_id 
      FROM relatives 
     WHERE person_id IN (%father_id%, %mother_id%);
INSERT INTO relatives VALUES (%new_person_id%, %new_person_id%);
  • 2 人が同じ遺伝子系統に属している場合、繁殖することはできません。

上記の構造では、かなり単純です。field にrelatives同じ値を持つ2 つのレコードを探す必要がありancestor_idます。例えば:

    SELECT COUNT(*) 
      FROM relatives ra 
INNER JOIN relatives rb ON ra.ancestor_id = rb.ancestor_id
     WHERE ra.person_id = %person_a_id%
       AND rb.person_id = %person_b_id%

この構造ですべての祖先と子を探すのは非常に簡単です。しかし、直接の親/子のルックアップを高速化するために、非正規化アプローチ (つまり、father_id と Mother_id を最初のテーブルに格納する) をお勧めします。実際には、最初のテーブルだけで実行できます。

これをより実用的な色で示すために、実際に機能する (少し短いですが) SQL Fiddleの例を次に示します。)

于 2012-07-07T09:00:43.207 に答える