Take the 2-minute tour ×

I am currently designing a web application which will be used by many businesses. However, I am having trouble deciding how to store the data. The general structure of the data is demonstrated in this tree : http://i.imgur.com/lpYwqya.png

So there will be a table that lists every client. Each client has its own users and projects. Each project has two children: users and tasks. Users refers to the users registered under the client who are allowed to access that project (will store the id of that user, and their permission [read/write]) For each level of the tree, I need to store data. For instance, a task has the following fields (WBS, Name, Start Date, Finish Date, Duration, Work, Cost, Fixed Cost, Vendor, ...)

I am having difficulty deciding how to best structure the data. Note that the data will always be accessed from the top of the tree down (parents to children), and I never have to move across children or back up the tree. Here are two solutions I have come up with:

Solution 1: Have an unlimited number of tables. Every time a client is created, two tables are also created: 1_projects and 1_users (where 1 is the id of the client in the first table). When a project is created, a table 1_1_tasks will be created, and so on. So the plan table for a risk with id 5, task id 3895, project id 19, and client id 57658 would be: 57658_19_3895_5_plans.

Solution 2: Have 9 tables: clients, users, projects, project_users, tasks, risks, risk_updates, plans, plan_updates. In the risks table, in addition to the fields that every risk has associated with it, it will also have the following: client_id, project_id, task_id. So, for example, if I want to return every risk that a client has for a particular task, I search the entire tree for risks where client_id = #, project_id = #, task_id = #. Of course, these fields would form a composite/compound key for the risk table. So, the risk table would store the risks for every task, from every project, from every client. The last table, plan_updates, would obviously be massive.

I believe solution 1 to be strong because it allows me easily navigate down the tree because nodes that do not belong to the same parent are not stored in the same table. However, this solution is also very bad because there will be a massive number of tables, and so any later modifications to the database would be very difficult.

Solution 2 is strong because all risks are centralized in one table. However, I wonder whether it will be very inefficient when searching say, the plan_updates table because I will have to search the entire table (which will be massive) for fields that match the id's of all parent elements.

To put this all into perspective, I anticipate the following:

Users: 1-20 per client. Usually less than 5.

Projects: 1-100 per client. Most will be less than 20.

Tasks: 100-10,000 per project.

Risks: 0-10 per task. Only around 30% of tasks will have risks though, and the majority of these will only have 1-4 risks.

Risk Updates: 1-10 per risk.

Plans: 1-5 per risk.

Plan Updates: 1-10 per plan.

If anyone could shed some light on how I could best solve this problem, that would be very helpful.

share|improve this question
Your intuition that solution 1 is bad is correct, it goes against the whole purpose of databases. Your (incorrect) intuitions about the efficiency of solution 2 suggests that you really should read an introductory book about databases. –  msw Aug 14 '13 at 5:29
add comment

2 Answers

up vote 1 down vote accepted

The second solution seems much more reasonable to me. The biggest flaw in the first solution would be the poor manageability of the whole structure. You will very soon end up with a massive number of tables and in case of a structure change (an extra field or an extra constraint needs to be added) you will have trouble.

Your concerns for compound keys are not that serious on the other hand.

Tasks for example can be assigned to individual projects alone. There is no need for them to have a reference directly to client too. On the other hand it is very likely that you will at some point introduce another n-n link table connecting the users and tasks directly in order to define who is to carry out that particular task.

So, if you want to list all the risks of a task you will first have to find the task at hand and then use a single key (the task id) to scan the risks table. That remains the same whether you have one or multiple tables.

I strongly suggest you choose soution #2 and make sure you identify all the relevant primary keys and indexes (and unique columns where applicable). That will make the database fast and efficient.


As @MSW mentions there is a whole lot more to be said about the subject. There is endless literature about database design (with principles like normality, atomicity ...) that covers the subject.

One further point that explains the poor quality of solution #1 would also be that at a later point you will not easily be able to do analyses across various projects since they will all be in a large number of different tables.

share|improve this answer
add comment

Stay away from your solution #1. Better stick to your solution #2 but with a few changes.

Your Risks table does not need these keys: client_id, project_id, task_id. You would only need task_id (as the foreign key) since your Tasks table is already associated with your Projects. Same as with the Plans, Risk Updates and so on. Like you have mentioned, you always access it from the top-down (join the tables from projects to tasks to risks and so on).

share|improve this answer
add comment

Your Answer


