php - Inbreeding-immune database structure -


i have application requires "simple" family tree. able perform queries give me data entire family given 1 id member in family. simple because not need take account adoption or other obscurities. requirements application follows:

  • any 2 people not able breed if they're same genetic line
  • needs allow addition of new family lines (new people no previous family)
  • need able pull siblings, parents separately through queries

i'm having trouble coming proper structure database. far i've come 2 solutions they're not reliable , out of hand quite quickly.

solution 1 involves placing family_ids field on people table , storing list of unique family ids. each time 2 people breed lists checked against each other make sure no ids match , if checks out merge 2 lists , set child's family_ids field.

example:

father (family_ids: (null)) breeds mother (family_ids: (213, 519)) -> child (family_ids: (213, 519)) breeds random person (family_ids: (813, 712, 122, 767)) -> grandchild (family_ids: (213, 519, 813, 712, 122, 767)) 

and on , forth... problem see lists becoming unreasonably large time goes on.

solution 2 uses cakephp's associations declare:

public $belongsto = array( 'father' => array( 'classname' => 'user', 'foreignkey' => 'father_id' ), 'mother' => array( 'classname' => 'user', 'foreignkey' => 'mother_id' ) ); 

now setting recursive 2 fetch results of mother , father, along mother , father, , on , forth way down line. problem route data in nested arrays , i'm unsure of how efficiently work through code.

if able steer me in direction of efficient way handle want achieve tremendously helpful. , appreciated , i'll gladly answer questions has. lot.

in sql (more correctly, rdbs) i'd use following solution:

1) create table people following fields - id, name, father_id, mother_id. first 1 typical primary key column, father_id , mother_id refer column nullable (to allow addition of new family lines).

2) create table relatives following fields - person_id, ancestor_id. both not null, both form composite primary key, both fk person.id.

and that's it. no, really! ) consider tasks:

  • add people without family lines

that's pretty doable: insert people (name) values ('some_name'). trick make insert related fresh person relatives: insert relatives values (%new_person_id%, %new_person_id%)

what's for? consider common task: add person has both father , mother listed in tables already. structure it's done simple (after inserting corresponding record people, , getting person_id result)...

insert relatives select %new_person_id%, ancestor_id relatives person_id in (%father_id%, %mother_id%); insert relatives values (%new_person_id%, %new_person_id%); 
  • any 2 people not able breed if they're same genetic line.

with structure described above it's rather simple: have 2 records in relatives has same value in ancestor_id field. example:

 select count(*) relatives ra inner join relatives rb on ra.ancestor_id = rb.ancestor_id ra.person_id = %person_a_id% , rb.person_id = %person_b_id% 

it's quite easy ancestors , children in structure; i'd still prefer de-normalized approach (i.e., storing father_id , mother_id in first table) speed look-up direct parents/children - can done first table alone.

here's working (albeit bit short) sql fiddle example show in more practical color. )


Comments

Popular posts from this blog

javascript - backbone.js Collection.add() doesn't `construct` (`initialize`) an object -

php - Get uncommon values from two or more arrays -

Adding duplicate array rows in Php -