I have the details of the members of my family in a database. I want to generate a web page with a family tree generated dynamically by reading from the table.
My table schema looks like this
id(int) name father(int) mother(int) spouse(int) dateOfBirth
where father, mother, and spouse are referencing the id column of the same table. The root node will have null for father and mother.
Given this data how can I go about dynamically generating the family tree. I am new at designing tables, so if this design is sub optimal kindly suggest another schema from which this objective can be achieved.
Any pointers on how to atleast get started would be highly appreciated.
Take a look at nested set model.
Your design looks ok, but with this design it's easier to insert nodes than to get them out of the table.
You can look at nested sets and implement that model. Nested sets are harder to update, but you can get the nodes of any subtree with a single query, so I think it matches your problem quite well (a family tree doesn't change too often :).
You would need some metadata, like relation type (Child, Sibling, Spouse) in addition to the nested sets parent-child relations, but I think you can add that easily.
This design is ok, but you would either select all the data and then build the tree on client side iteratively checking the returned array, or perform many subqueries, which is also not very good.
The best solution I know (for hierarchical structures, you've got spouses also) is storing the tree path in a string field. For example, you've got grandpa with id=1, children with id=2 and 3, 2 has children 4 and 5. Then, they have paths, respectively, "", "1", "1", "1,2", 1,2".
You can use this structure to retrieve the tree elements in order, using ORDER BY path clause.
Related
I am developing a software for creating and storing print layouts.
A layout consists of a series of pages.
Each page has one or more columns
Within each column there will be one ore more elements
Elements within a column are ordered: There is a fixed sequence of elements
Elements may be of type "text" or "image" (for the sake of simplicity, in reality there are many more types)
Different elements have different properties. Eg. images have a resource url, text has a font. See example code at end of posting.
My question is about modelling the relation between columns and elements.
Idea #1: One table for all elements
This would be really straight forward. Add all properties as columns to a table and use N:N relation to model the relation between columns and elements.
Relation could look like this
column_idelement_idorder
000000010000000010009
000000010000000020012
000000020000000060003
This seems not very appealing to me as the table to store elements would be polluted with empty entries, e.g. all font columns would be empty for image elements. It gets even worse if I consider all different erlement types I have (about 10).
Benefit: SQL queries are relatively simple:
select * from
relation_table R inner join elements E
on R.element_id = E.id
where R.column_id = FIXED_COLUMN_ID
Idea #2: One table for each type of element
Modelling the elements would be quite simple, just create one column for all properties of class element and add the properties of the specific element type like image.
But how about modelling the relation column:element?
My first approach would be to try to add a column to the relation that specifies the type of element which would directly map to the related table:
column_idelement_idorderelement_type
000000010000000010012text
000000010000000020003image
000000020000000060005image
This certainly works but all sql queries to retrieve the elements for a specific column would get quite complicated.
Questions
Is there an approach that combines the simplicity of sql queries from Idea #1 and the more accurate database modelling of Idea #2?
How do you approach this problem?
P.S.: Under other circumstances I would switch to a nosql based database but that's not possible :-(
<?php
// Sample code of element structure
class element {
protected $id;
protected $order;
// more properties, getters and setters...
}
class image extends element {
protected $image;
// more properties, getters and setters...
}
class text extends element {
protected $font;
// more properties, getters and setters...
}
?>
I think you are better off starting with one table for elements and then adding join tables for extra info required for various element types.
It is usually a mistake to think about modeling data as real-world entities in db design but much better to take a step back and model based on the inner dependencies of the data. These often coincide (and do so just often enough to make real-world entity focus look attractive) but when you run into cases where they don't it will cause you grief.
Here, you have issues regarding querying and ordering which are trivial to solve in a single table but will give you big headaches with many tables.
Let me focus on the messy part: "Different elements have different properties. Eg. images have a resource url, text has a font." This begs, as you say, for lots of nullable columns or lots of different tables. In either case, it is a mess.
A solution... Put those "different elements" in a JSON collection of stuff. Put it in a column and let the application decode it and make use of the stuff.
With that solution, the structure is still in the database, but the details are left for the application. Seems like a fair tradeoff.
See other discussions of EAV.
I'm currently working on an app backend (business directory). Main "actor" is an "Entry", which will have:
- main category
- subcategory
- tags (instead of unlimited sub-levels of division)
I'm pretty new to OOP but I still want to use it here. The database is MySql and I'll be using PDO.
In an attempt to figure out what database table structure should I use in order to support the above classification of entries, I was thinking about a solution that Wordpress uses - establish relationship between an entry and cats/subcats/tags through several tables (terms, taxonomies, relationships). What keeps me from this solution at the moment is the fact that each relationship of any kind is represented by a row in the relationships table. Given 50,000 entries I would have, attaching to a particular entry: main cat, subcat and up to 15 tags might slow down the app (or I am wrong)?
I then learned a bit about Table Data Gateway which seemed an excellent solution because I liked the idea of having one table per a class but then I read there is virtually no way of successful combating the impedence missmatch between the OOP and relational-mapping.
Are there any other approaches that you may see fit for this situation? I think I will be going with:
tblentry
tblcategory
tblsubcategory
tbltag
structure. Relationships would be based on the parent IDs but I+'m wondering is that enough? Can I be using foreign key and cascade delete options here (that is something I am not too familiar with and it seems to me as a more intuitive way of having relationships between the elements in tables)?
having a table where you store the relationship between your table is a good idea, and through indexes and careful thinking you can achieve very fast results.
since each entry must represent a different kind of link between two entities (subcategory to main entry, tag to subcategory) you need at least (and at the very most) three fields:
id1 (or the unique id of the first entity)
linkid (linking to a fourth table where each link is described)
id2 (or the unique id of the second entity)
those three fields can and should be indexed.
now the fourth table to achieve this kind of many-to-many relationship will describe the nature of the link. since many different type of relationship will exist in the table, you can't keep what the type is (child of, tag of, parent of) in the same table.
that fourth table (reference) could look like this:
id nature table1 table2
1 parent of entry tags
2 tag of tags entry
the table 1 field tells you which table the first id refers to, likewise with table2
the id is the number between the two fields in your relationship table. only the id field should be indexed. the nature field is more for the human reader then for joining tables or organizing data
Using PHP & Mysql-
I have a list of 120,000 employees. Each has a supervisor field with the supervisor employee number.
I am looking to build something that shows the employees in a tree like format. Given that if you click on anyone that you have an option to download all of the employees (with their info) that are under them.
So two questions - should I write my script to handle the query (which I have but is SLOW) or should create some sort of helper table/view? I am looking for best practice behind this.
Also I am sure this has been done a million times. Is there a good class that handles organization hierarchy?
The standard way of doing this is to use one table to store all of the employees, with a primary key field for the employee_id, and a field for supervisor_id which is a 'self join' - meaning that the value in this field points back to the employee id of this employee's supervisor. As far as displaying the employee tree - for relatively small trees, the entire tree structure can be sent to the client's browser when the page is created, and tree nodes can be displayed as the nodes are clicked from the stored data. But, for larger trees, it is better to fetch the data as needed, i.e. when the nodes are clicked. If you have 120,000 employees, then you might want to use the later approach.
Let's say I have a bunch of businesses. And each business can have multiple categories, subcategories and sub-subcategories (three levels). Let's say I set up a table according to the nested set model for my categories.
How do I now use this table and assign categories to each business? I understand I will need another table but what node gets assigned? Is it the lowest level node?
business_id category_id
And then what's the right way to retrieve all the categories for each business?
The way this generally works is that you assign the leaf or lowest-level-node. Then when you are querying to get the full hierarchy you traverse up the tree to the root. It is generally much easier (especially in MySQL) to traverse from leaf to root then vice versa.
Here is the best link I've found that describes how to accomplish this query for a tree of dynamic size (the link you've included assumes that the tree is always 3 levels deep)
I need to build a family tree in php and MySQL. I'm pretty surprised at the lack of open source customizable html family tree-building software there is out there, but I digress. I have spent a lot of time reading about storing MySQL digraphs and family trees. Everything makes sense to me: have a table with nodes (people) and a table with edges (relationships).
The only problem I have is I'm not sure of the best way to store relationships that are not necessarily adjacent, for example sibling and grandparent relationships. At first I didn't think this would be a big deal because I can just invisibly enforce a parent (everyone has parents) that would resolve these connections.
However, I also need to be able to store relationships that may not have a common parent such as romantic partners. Everything I have read suggests a parent-child relationship, but since romantic partners do not share a common parent (hopefully), I'm not sure how to store it in the edges table. Should I use a different table, or what? If it's in the same table, how do I represent this? As long as I am doing this with non-familiar relationships, I might as well do it with family too.
To sum up, three questions:
How do I represent lateral relationships?
If a lateral relationship has a common parent, how do I store it? Should this be a family flag on the table where other lateral relationships are stored?
How do I store parent-child relationships where the child is two or more edges away (a grandparent), but the immediate parent is unavailable?
Any help is appreciated, and if anyone has any suggestion for some javascript/html family tree building software, that would be wonderful.
An idea that comes from the Geneapro schema and RootsMagic.
person
------
person_id
name (etc)
life_event_types
----------------
life_event_type_id
life_event_type_description (divorce, marriage, birth, death)
life_events
-----------
life_event_id
life_event_type_id
life_event_description
life_event_date
life_event_roles
----------------
life_event_role_id
life_event_role (mother, father, child)
person_event_role
-----------------
person_id - who
life_event_id - what happened
life_event_role_id - what this person did
So you could have a life event of type "birth", and the role_id tells you who were the parents, and who was the child. This can be extended to marriages, deaths, divorces, foster parents, surrogate parents (where you might have 3 or 4 parents with a very complicated relationship), etc.
As for storing more distant relationships, you can calculate these. For example, you can calculate the Father of anybody by getting the person who has the 'father' role with a matching event_id. You can then get the father of that person, and you have the grandfather of the original person. Anywhere that somebody is unknown, create the person with unknown data.
person
-------
person_id
other_stuff
relation
----------
person_id_1
person_id_2
relationship_type
begin_dt
end_dt
just populate the relationship type with any value you are interested in. (FK to some picklist would be great)
I put the dates on for an interesting subdiscussion/thought provokation.
The GEDCOM data model and the Gramps data model are two of the most popular formats for exchanging geneological data between different tools. Using either of these data models should both (1) make your tool more compatible with other tools and (2) ensure that your data model is compabible with many special cases, considering both data models are specially designed to deal with geneological data.
Tools like Oxy-Gen or the Gramps PHP exporter should get you on your way with respect to how to import GEDCOM data into a database.
For more details, see also my answer to “Family Tree” Data Structure.