views:

34

answers:

1

I'm building a web application and I just received some basic foundation data from the client in a spreadsheet. I need to get the data into a MySQL database in a meaningful way so I can effectively query it later. What makes the most sense? Here's the particulars:

There are Departments, Classes *edit (classes are types of products like mens t-shirts, womens jeans etc...) and Vendors (and Products eventually...). 25 Departments, 300 Classes and 3300 Vendors. Departments share Classes as well as Vendors in some cases.

My web application will have Department pages that will display a list of vendors who have products that appear in the chosen department with a link to a vendor specific page. The vendor page will list their products sorted by class.

I could set up 3 or 4 tables I suppose but will that result in a well formed, efficient query when I build my application? Also, will that make for a normalized database that avoids update, delete anomalies?

This could really be more a question of how to select my data rather than how to structure my DB, but I figured I would start with structure and move to the query optimization.

+1  A: 

If I assume correctly that Classes are categories of products, and a product can belong to a single class:

+================================+    +================================+
| departments                    |    | vendors                        |
+----+------+--------------------+    +----+------+--------------------+
| id | name | others             |    | id | name | others             |
+====+======+====================+    +====+======+====================+

+================================+    +================================+
| classes                        |    | products                       |
+----+------+--------------------+    +----+----------+----------------+
| id | name | others             |    | id | class_id | name | others  |
+====+======+====================+    +====+==========+================+

+================================+    +================================+
| departments_vendors            |    | classes_departments            |
+----+----------+----------------+    +----+---------------+-----------+
| id | department_id | vendor_id |    | id | department_id | class_id  |
+====+==========+================+    +====+===============+===========+

+================================+
| products_vendors               |
+----+------------+--------------+
| id | product_id | vendor_id    |
+====+============+==============+

If products can belong to multiple classes, drop the class_id column and make a new table called classes_products.

Assuming the above structure, here is a sample query.

Get one department, that department's classes, and products for those classes:

SELECT    departments.id   AS DepartmentId,
          departments.name AS DepartmentName,
          classes.id       AS ClassId,
          classes.name     AS ClassName,
          products.id      AS ProductId,
          products.name    AS ProductName
FROM      departments
LEFT JOIN classes_departments
       ON classes_departments.department_id = departments.id
LEFT JOIN classes
       ON classes.id = classes_departments.class_id
LEFT JOIN products
       ON products.class_id = classes.id
WHERE     departments.id = ##

The best way to get a list of vendors who sell products from a class for a department would be to make another table called classes_vendors

Stephen
This proposes creating 7 tables, correct? Is this the best choice for scalability and normalization of data? I'm new enough to relational data that I don't really know for sure. I just want to keep it as simple as possible so I don't end up with any issues later...
Ofeargall
From my experience, the simplest normalization should focus on objects and relationships. You have `Departments`, `Vendors`, and `Products`. `Classes` are not as tangible, but since you have 300 of them they should be in their own table. That's four. Then you need to look at relationships. for a One->HasMany relationship, but a foreign key from the parent in the children's tables (`class_id` in `Products`). For special relationships that can be shared both ways (known as HABTM or "Has And Belongs To Many"), like Departments and Classes, a join table is the best/easiest way to store it.
Stephen
It is possible that my relationships are not exactly what you have in mind. You'll need to formulate how each object will be related (Maybe products can have more than one class, and if so there should be a new table to define that HABTM relationship). After you know how each piece relates, you can figure out the tables you need.
Stephen
Actually, the CakePHP documentation has an excellent section on relating your models.. you should check this out and apply the same techniques to your data: http://book.cakephp.org/view/78/Associations-Linking-Models-Together Of particular note are the sections on relationships and Schemas
Stephen
Excellent. Thank you for clarifying that for me, Stephen. I appreciate the help. I'll need to get my head wrapped around this and start coding. You've laid it out nicely for me. Big thank you for the query sample as well.
Ofeargall
You're welcome!
Stephen
Stephen. I think I'm getting this after no small amount of time with a dry-erase pen and a white board. I have a couple questions, are departments_vendors, classes_departments and products_vendors actual tables in my schema or do they exist only as a representation of what you're trying to achieve in the query? And, if I only want to show the vendors for a department I'll need to do something like a left join of classes_departments on deptID, then left join of vendors based on the result of the previous left join, all based on the department ID, correct? Sorry for the verbosity.
Ofeargall
Stephen
To show the vendors for a department, you would select from the departments table, and then left join the departments_vendors table, and then left join the vendors table. Basically, you would "walk down the relationship chain"
Stephen
Ah, right. Again, thank you for clarifying. I think I was trying to get at the vendors in a different and likely less elegant manner. I'm pretty good at relationships, just not these kinds...
Ofeargall