Polymorphic relation use cases with Laravel - Design Database - mysql

I try to design my database and I get confuse.
In my app, an user belong to a group and this group may have multiple stocks of only one type of equipement.
Those stocks can be of two types:
Stock of power lines
Stock of windturbine
Each stock has an identifier representing the area.
Each stock has multiple equipements.
So, to summarize :
User A belongs to group A.
Group A has :
Windturbine1 which has 5 individual windturbines
Windturbines2 which has 10 individual windturbines
User B belongs to group B.
Group B has :
power_lines1 which has 10 individual powerlines
I tried to represent this scheme like this :
However, I'm not totally convinced. I'm not sure if the stock table need to be polymorphic with windturbine_area and power_line_area.
Any insights on this please ?

Related

Database Design for a system that has Facebook like groups

I'm creating a system that has Groups. These can be thought of like Facebook Groups. Users can create new groups. Currently I have the following types of groups:
City Group - Groups based on a certain city. For example "London Buy and Sell Group"
School Group - Groups based on schools. For example "London University Study Group"
Interest Group - Groups that are not tied to a place. For example "Over 50's Knitting Group"
In the future more group types will be added. Each group can have different types of options, but all groups have the same basic data:
An ID
A creator ID
A name
An option description
I'm struggling on putting together a database design for this. My initial thought was to create different tables for the different groups.
For example have a single table called group. This table has an id, creator id, name, description, member count, timestamps.
Then have other tables to represent the other groups, and link them to group. So I have a city_group table that contains and id, group_id, city_id. And the same for the other group types.
The only problem I have with this is interest_group doesn't have any extra data that a normal group. But for the purpose of being able to query only Interest Groups I thought it might make sense to create an interest_group table. It would only have the following columns: id, group_id, timestamps ... which seems a bit wasteful to have a table just for this purpose.
Here's a diagram to make things easier:
Are there any issues with my solution, or any better ways to solve this design problem?
I've got an idea, which is a workaround basically: have another table like: group_type in which you have id(the PK) and then you have tablename (the full table name of the type).
Then, you should have a FK from your Group table linking to this group_type table.
id tablename
--------------------
1 School Group
2 Interest Group
After all this is done, you could build your queries based on the values from this table, as an example:
JOIN (SELECT tablename FROM group_type WHERE id=group.group_type_id) ON ..

What are the ways to model multivalued M : N relationship?

I am working on the project that requires multivalued M : N relationship.
For eg.
There is a list of products in the Products table.
The user can purchase 1 or more products and are maintained in the table Orders. Along with this information, there is one more table that maintains analytical information.
This table should contain the hard coded data like. If the order contains product 1 and product 2 then does product 3 and product 4 also appeared in the user's order. These are basically hard coded rules
actual products | expected products
1,3 | 2,4
5,6,7,8 | 3,4
Now from these tables, I need to find information like if user's order number 1 had products like 1 and 3 then return 2 and 4.
I need suggestions as to how to describe this multivalued M to N relationship. If there are any other options other than RDBMS feel free to suggest. Thanks
You could create three additional tables:
ProductSet(productset_id) - Stores product sets headers(one row from your sample)
ProductSetPart(productset_id,product_id) - Stores required products to make set, in your case column actual product
ProductSetAdditional(productset_id,product_id) - stores expected products.
Having given Order we can detect which additional products should be added.
EDIT: sample added
Example query that return list of Sets that are fulfilling requirements:
SELECT psp.productset_id FROM
ProductSetPart psp LEFT JOIN
OrderLines ol
ON
psp.product_id=ol.product_id
GROUP BY
psp.productset_id
HAVING
-- trick - COUNT(*) will return count of all products required by aggregatet set
-- COUNT(psp.product_id) will count only not null products
-- (which will be null if they aren't in order line)
-- so if all product sets are in order line then we know,
-- that this set requirements are full filled
COUNT(*) = COUNT(psp.product_id)

Get stats table from a many to many relationship

I have a pivot table for a Many to Many relationship between users and collected_guitars. As you can see a "collected_guitar" is an item that references some data in foreign tables (guitar_models, finish).
My users also have some foreign data in foreign tables (hand_types and genders)
I want to get a derived table that lists data if I look for a particular model_id in "collected_guitar_user"
Let's say "Fender Stratocaster" is model id = 200, where the make is Fender (id = 1 of makes table).
The same guitar could come in a variety of finish hence the use of another table collected_guitars.
One user could have this item in his collection
Now what I want to find by looking at model_id (in this case 200) in the pivot table "collected_guitar_user" is the number of Fender Stratocasters that are collected by users that share the same genders.sex and hand_types.type as the logged in user and to see what finish they divide in (some percent of finish A and B etc...).
So a user could see that is interested in what others are buying could see some statistics for the model.
What query can derive this kind of table??
You can do aggregate counts by using the GROUP BY syntax, and CROSS JOIN to compute a percentage of the total:
SELECT make.make, models.model_name as model, finish.finish,
COUNT(1) AS number_of_users,
(COUNT(1) / u.total * 100) AS percent_owned
FROM owned_guitar, owned_guitar_users, users, models, make, finish
CROSS JOIN (SELECT COUNT(1) AS total FROM users) u
WHERE users.id = owned_guitar_users.user_id
AND owned_guitar_user.owned_guitar_id = owned_guitar.id
AND owned_guitar.model_id = models.id
AND owned_guitar.make_id = make.id
AND owned_guitar.finish_id = finish.id
GROUP BY owned_guitar.id
Please note though, that in cases where a user owns more than one guitar, the percentages will no longer necessarily sum to unity (for example, Jack and John could both own all five guitars, so each of them owns "100%" of the guitars).
I'm also a little confused by your database design. Why do you have a finish_id and make_id associated directly in the owned_guitar table as well as in the models table?

mysql calculation based on the conditions into a column

I have a t_personne table.
I encodes a general form for each person.
I also encodes a table "interview" (t_entretien) a presence per project (proj_id).
For the project, it can have multiple actions.
The project action "RAE" are encoded: 2-01.01, 2-02.01, 2-02.02 ...... 2-03.01, 2-03.02, etc.
I have a following calculation rule: A unit is equal to 2 actions from two different categories into the actions encoded.
For example, a person with one action 2-02.01 and 2-03.01 with 2-03.04 actions will only be counted as one unit.
A person who has 4 shares of 2-03 types will not count.
I have to calculate the total number of units.
I started thinking:
SELECT COUNT(*) AS Expr1
FROM (SELECT t_entretien.id
FROM t_entretien
INNER JOIN
t_action on t_action.cact_caction = t_entretien.ent_id
GROUP BY t_entretien.id
HAVING(COUNT(DISTINCT t_action.cact_caction) > 1)) AS derivedtbl_1
Here is a little FIDDLE http://sqlfiddle.com/#!2/6c831/1
Thanks for all !
EDITION
The context is the following.
I get a person (t_personne) and using a form I introduce general data.
This person, I enrolled into a project (t_projet) at the time of the interview (t_entretien).
During the interview, I realize actions.
Every actions are specific projects (t_action).
For the project, including the "cact_code" is 2, I chose different actions encoded (see table t_codeaction).
My problem is the following. I must calculate the number of actions based on a formula that is imposed on me: one unit = 2 actions belonging to different categories. Categories are identified as follows (t_codeaction): 2-01 this category has only one action (2-01.01), the following category includes 4 actions 2-02 and 2-03 in the third category includes 12 actions, etc.
Imagine that the person "ent_id" = 8105 received four actions, one in the category 2-01.01 and 2-03 in the other 3. It is one and only one unit under the rule as it has received at least two actions two different categories. 3 actions in the 2-03 category account for an action. Thus, the person whose "ent_id" = 8114 received only 3 actions of the same class 2-03, this unit is 0.
I am probably wildguessing because the question is bad described, but anyway, something like this?
SELECT id as entretiedId, count(*)/2 as units from
(SELECT t_entretien.id, SUBSTRING(t_action.cact_caction,1,4) as CATEGORY, COUNT(*)
FROM t_entretien
INNER JOIN
t_action on t_action.ent_id = t_entretien.ent_id
GROUP BY t_entretien.id, CATEGORY) as t_derived
GROUP BY id having count(distinct category) > 1
The derived table counts actions, but with one row per ent per category. then the outer group by counts the subactions per category, and divides by two for calculating the units.
fiddle: http://sqlfiddle.com/#!2/6c831/22/0

Filter one table based on values from another table column

I have a table "PackagingType" with 2 columns (materialID | name) and another table "materials" with ID and material details.
For each name from the "packagingtype" I want to assign what materials are available (e.g. in material ID column I would have 1,3,4,5).
I need to match these materialsID with materials table and pull out the details.
What would be the correct way to do it? Not sure if storing data as 1,3,4,5 is the right was and what would be the syntax look like?
In relational database design you don't combine values into one cell. There are exceptions but are few and far between. This would would not be normalized data and would make future query and analysis difficult/complex. So the PackagingType should have the same name multiple times for different materialIDs.
So the table would have data like
MaterialID Name
1 PackageA
3 PackageA
4 PackageA
5 PackageA
Then to get results with the material description you'd simply do a join.
SELECT PT.MaterialID, PT.Name, M.Detail
FROM PackagingType PT
INNER JOIN Materials M
on PT.MaterialID = M.MaterialID