Laravel, Products with Attributes in a many-to-many table - mysql

I'm building a platform where Suppliers can add products, and shop owners can 'copy' those products to their shops and sell them.
A Supplier can create products, and he can add all sorts of attributes to them, like the size, colors.
When a Shop wants to use one of the Supplier's products, he can choose which attributes he wants to offer. For example if the Supplier has a T-Shirt in offer with 3 sizes. The shop may choose to sell that T-Shirt with only 2 sizes.
So I have a Products table which looks like this. The Supplier adds products in here.
+----+-------------+-------+
| id | description | price |
+----+-------------+-------+
| 1 | T-Shirt | 10 |
| 2 | Car | 100 |
+----+-------------+-------+
I have a Product attributes table, Which is also filled by the Supplier
+------------+-------------+------------------------------+
| product_id | description | options |
+------------+-------------+------------------------------+
| 1 | size | ["small", "medium", "large"] |
| 1 | color | ["white", "black"] |
+------------+-------------+------------------------------+
Shop Side
When a Shop owner wants a Product. I make a record in the shop_products table, referencing which Shop wants what Product, and adding an optional image, as following
+---------+------------+-----------+
| shop_id | product_id | image |
+---------+------------+-----------+
| 1 | 2 | image.jpg |
| 1 | 3 | image.jpg |
+---------+------------+-----------+
Now the only issue remaining is: How do I make sure the Shop can choose which attributes he wants to take.
Should I create a shop_product_attributes table.. But I can't put a relation on the many-to-many because it doesn't have an id?

If its possible to change your database structure i would do it this way, i know its a bit of a change to what you have but i think you have to think of a product as a relation, this is because though a t-shirt is a product the actual t-shirt black medium is a completely different product to a t-shirt black small and your suppliers will almost certainly referecne them this way
Your products table would look like this but its not your primary table referencing products, this holds the generic stuff that a product will have such as a description
or a name
+----+-------------+-------+-----------+-------------+
| id | name | price | image | description |
+----+-------------+-------+-----------+-------------+
| 1 | Super-T | 10 | image.jpg | some text |
| 2 | Focus | 100 | image.jpg | some text |
+----+-------------+-------+-----------+-------------+
Your primary table would be a sku table think of this as your product, if you have any sku specific stuff you would put them here
+----+-------------+------------+--------------+
| id | sku | product_id | category |
+----+-------------+------------+--------------+
| 1 | p1-cb-m | 1 | t-shirt |
| 2 | p2-cb-s | 2 | t shirt |
+----+-------------+------------+--------------+
Then have a attributes_sku table, this will link the sku to the attribute
+---------------+--------------+
| sku_id | attribute_id |
+---------------+--------------+
| 1 | 1 |
| 1 | 2 |
+---------------+--------------+
Attributes for normalisation
+----+-------------+------------+
| id | type | name |
+----+-------------+------------+
| 1 | color | black |
| 1 | size | medium |
+----+-------------+------------+
Shop Sku table
+---------+------------+
| shop_id | sku_id |
+---------+------------+
| 1 | 1 |
| 1 | 2 |
+---------+------------+
the advantages of this is you can do
foreach $shop->skus where category = t-shirt to display all their t-shirts
then you can do $skus->product->name
$skus->product->attribute->name or better yet set a relationship on the sku model to be say colour $this->attribute->where('type', color);
Note
A small note i'd further normalise this by having a categories and types table, so your attributes type would actually be a type_id that is a belongs relationship to a types table, and your sku category would be a category_id, to a categories table, this is so in the future if you category or type decides to change name you dont have to edit 1000s of records etc

Actually, you can create a many-to-many relation in shop_product_attributes table.
Since your Product Attributes table has a compound key of 2 fields: [product_id,description], your many-to-many relation will have a trinary-key - [shop_id,product_id,description] where [product_id,description] is used as a reference foreign-key as well.

Related

How to change the integer to string in a lookup table?

I cannot understand why joining tables are so difficult for me... But i would like to change a foreign key (platform_id) to the name from the lookup table. Dont know if this is the best approache, but should give me the best scaling options in the future.
Table companys
+----+--------+-------------+
| id | name | platform_id |
+----+--------+-------------+
| 1 | apple | 1 |
| 2 | google | 2 |
+----+--------+-------------+
Table platforms
+----+----------+-------------------+
| id | name | data |
+----+----------+-------------------+
| 1 | Software | {'market cap':''} |
| 2 | Retail | {'market cap':''} |
| 3 | Medicin | {'market cap':''} |
+----+----------+-------------------+
Expected result
+----+--------+-------------+
| id | name | platform_id |
+----+--------+-------------+
| 1 | apple | software |
| 2 | google | retail |
+----+--------+-------------+
What if i would like to also have the data column from platsforms table?
Use JOIN & create a view :
CREATE VIEW company_view
AS
SELECT c.id, c.name, p.name as platform_id, p.data
FROM company c INNER JOIN
platform p
ON p.id = c.platform_id;
If you want to change foreign key constraint to string value instead of platform_id. So, it is not advisable. Think if you need to change the name of platforms, you need to change ever where instead of one table.

Mysql database design with users, groups teams and more

Need help trying to figure out what the best way to go would be when different kind of objects from different tables with their own auto incremented id need to interact with the same object.
Facebook have this for example. You can both like a post as a group/page and more but you can also like a post as a single user.
So i am trying to figure out how i can achieve this in the best and most efficient way.
This is what i have so far and how i think it could work but i would really need a second opinion on this.
Lets say i have the following tables for example
users
+----+----------+----------+-----------+
| id | username | password | more cols |
+----+----------+----------+-----------+
| 1 | User1 | changeme | etc |
| 2 | User2 | changeme | etc |
| 3 | User3 | changeme | etc |
+----+----------+----------+-----------+
groups
+----+------------------+-----------+
| id | name | more cols |
+----+------------------+-----------+
| 1 | We who like cats | etc |
| 2 | Funny videos | etc |
| 3 | Nice food pics | etc |
+----+------------------+-----------+
teams
+----+----------------+-----------+
| id | teamname | more cols |
+----+----------------+-----------+
| 1 | Team Alpha | etc |
| 2 | Team Golden | etc |
| 3 | Team Foo | etc |
+----+----------------+-----------+
All of these objects should be able to interact with something created by another group, user, team or whatever. Now lets say that both team alpha and user3 likes something that the group funny videos has uploaded. I then need to know if there is a user, team or group that liked this to get the correct properties of the object that liked this upload.
Due to the fact that a user, team or group can have the same id i need something unique to know if i should look in the user, group or team table.
So i thought if i create the following table below that is used to interact with everything on the website and just points to the correct table depending on the type_id.
type_id 1 = users
type_id 2 = groups
type_id 3 = teams
+----+-----------+---------+
| id | object_id | type_id |
+----+-----------+---------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 3 |
| 5 | 1 | 3 |
+----+-----------+---------+
I then use object_id for every interaction that the user, group, team or whatever does.
Really appreciate all thoughts on this if there is a better way to do it :)
I believe there is another approach .
I can't comment that is why I answered .
in your "LIKES" tables you can have
team_id
group_id
user_id
So you will have smth like this
+----+-----------+---------+---------+---------+
| id | object_id | team_id |group_id |user_id |
+----+-----------+---------+---------+---------+
| 1 | 1 | 1 |NULL |1 |
| 2 | 2 | NULL|1 |NULL |
+----+-----------+---------+---------++---------+
You can have team_id , group_id, user_id either 0 or NULL when team/group/user has not liked and 1 if they do .
Once the row is generated for user or team next time you look if page has any like yet and if it does you just add team_id which liked the page or the post .
Hope it helps .

Deleting a Parent Record from a Look-up Table using a Join

I'm having trouble with SqlFiddle hanging so will try to explain simply with tables here.
I have three tables:
Orders
Items
Look-Up Table
The Look-Up table is necessary because of the way I receive data so I extract it into a table with single-items with OrderID and ItemID
Item Types
+----+----------+---------+
| ID | ParentID | Name |
+----+----------+---------+
| 1 | NULL | Clothes |
| 2 | 1 | Shirts |
| 3 | NULL | Food |
| 4 | 3 | Steak |
+----+----------+---------+
Orders
+----+---------+--------+
| ID | OrderID | ItemID |
+----+---------+--------+
| 1 | 1 | 1,2,3 |
| 2 | 2 | 1,3 |
+----+---------+--------+
Look-Up Table
+----+---------+--------+
| ID | OrderID | ItemID |
+----+---------+--------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 4 | 2 | 3 |
+----+---------+--------+
I now want to do join that grabs all of the item names for each order but I don't want "Parent Items" if a "Child Item" exists (e.g. if the order has Clothes and Shirts I don't want Clothes.
I am not sure why this Select/Delete query is challenging me so as I've done a number of them but it is escaping me for some reason.
Any Joins I do, even if I join either/both the Item Types table or the Look-up Table twice get me only:
The Single Child Record
Select L.ID,S.ID,S.ParentID fromLook-up TableL
Inner Join Orders O
On L.OrderID=O.ID
Inner JoinItem TypesS
On L.ItemID=S.ID
Inner JoinItem Types S2
On S.ParentID=S2.ID`
Both the Parent Records
Perhaps I've been working on this way too long because the answer seems obvious and I've done plenty of these this week but somehow this one is escaping me.
When SqlFiddle is back-up I will post one to make this a lot easier to debug, any thoughts in the interim appreciate.

How to create multiple related tables in mysql database

My title might not really convey what i'm trying to achieve, I have some tables which are related but i can't figure out how to create this relationship to make storing and retrieving data much easy. Below is what i was able to come up with.
color table
colorId(PK)
productId(FK)
colorName
size table
sizeId(PK)
productId(FK)
size
product table
productId(PK)
priceId(FK)
Qty
Name
Title
price table
priceId(PK)
productId(FK)
Now my problem is i have product with different variety for example
Men's blue addidas glide running shoes with productId 1, this product have different sizes and different color and the prices varies on sizes and color. example, if this pair of shoe color BLUE size 11 sells for $50, the same pair of shoe with bigger size and different color say size 12 color red might sell for $55, also this same pair of shoe color blue might have only size 11 available in stock and color blue size 12 of this pair might not be available, how do i create my table to save all the differences between color and sizes, and also prices. Any help on this, thanks
You probably shouldnt have every single attribute in it's own table, a potentially better way would be to have a product table and a variant table. This way you could have price, size, color, quantity available, etc all in the same table, then join on the product i.e. Men's blue adidas glide running shoes.
Your variant table would look something like this:
| variant_id | product_id | price | colour_id | size_id | quantity_available | in_stock |
| 1 | 1 | 50.00 | 1 | 11 | 20 | 1 |
| 2 | 1 | 55.00 | 2 | 12 | 0 | 1 |
Then you could load each variant individually, and have the quantity_available updated whenever you make a sale. I've also included an in_stock boolean so you can override whether stock appears on your site without having to adjust the quantity_available.
You'd then have the variant_id on the purchase table so you can join these later. Also, I like having sizes and colours on their own tables so you can put a taxonomy in place to aggregate all they blues say, or all the XS, S, M, L, XL.
Something like:
| colour_id | name | base_colour_id |
| 1 | Royal Blue | 3 |
| 2 | Spanish Blue | 3 |
| 3 | Blue | 3 |
| 4 | Ultramarine | 3 |
| 5 | Green | 5 |
| 6 | Mint Green | 5 |
This way you can add more unique colour variants and still report on base colours or full colour names. Here you'd use: SELECT * FROM variant_colour a JOIN variant_colour b ON b.colour_id = a.base_colour_id you'd get:
| colour_id | name | base_colour_id | colour_id | name | base_colour_id |
| 1 | Royal Blue | 3 | 3 | Blue | 3 |
| 2 | Spanish Blue | 3 | 3 | Blue | 3 |
| 3 | Blue | 3 | 3 | Blue | 3 |
| 4 | Ultramarine | 3 | 3 | Blue | 3 |
| 5 | Green | 5 | 5 | Green | 5 |
| 6 | Mint Green | 5 | 5 | Green | 5 |
This same idea can be used for sizes etc so you don't end up with hundreds of unique attribute variants that make your info impossible to report on.

Where (how) to store categories (sort of) tree in my database?

So, I am modeling a database using MySQL Workbench. I have a table called Category (two fields, id and description) and a table called Event. I would like to have a column in Event that holds any number of ids from Categories (as CSV, and their order is important).
How do I represent this in MySQL Workbench (in a ER model, I mean)? Or I am doing this really wrong?
It'll look something like this:
| ID | Descripion
| 1 | Lorem...
| 2 | Ipsum...
| 3 | Dolor...
| 4 | Sit...
| 5 | Amet...
| ID | Name | Categories
| 1 | John | 2,1,5,4
| 2 | Reese | 3,5,4
| 3 | Ben | 1,5
| 4 | Linus | 3,4,2
| 5 | Jack | 5
| 6 | Lemon | 4,5,2
(I've already read this: How to structure "categories" data in the database? but I am not sure I am in the same situation. My categories are more like a 'tree' than tags...)
For a many - many relationship you need an intermediate table which holds id's from both tables you're creating the relation between. On this table you can also set an ordering column which indicate how to sort your category.
| ID_Event | ID_Cat | Order
| 1 | 1 | 2000
| 1 | 2 | 1000
| 1 | 5 | 3000
| 1 | 4 | 4000
and so on.
You can choose to leave a nice gap in your ordering column by a 1000+ values so you can easily put in categories between existing ordered items.