Storing similar products with different attributes - mysql

I need to store similar products with different attributes (like length or color), should I add this products with different ids or as one product with many attributes?
Main problem that I need possibility to see quantities of products by attribute (4 red boots, 3 blue etc) and need to implement attribute selector on product page.
If create one id how to store attributes in cart table with selected attributes and how to manage quantities?
If create many ids it is easy to manage quantities but how to implement attributes selection?
I think about some SKU for linking product id with attributes and attribute values. But how to link all together?

If you're building an ecommerce site, this domain concept is generally known as "variant"; see here.
Typically, you have a "products" table containing the major attributes of the item, and a "variants" table, linked back to the product by product ID.
If you're only ever dealing with similar products, you can have the variant table contain columns for all attributes (e.g. size, price, colour); if you have lots of different types of variant (e.g. clothes, shoes, sports equipment), you are at the "inheritance modeling using relational databases"; see this answer.

Tables are there to store any data which you have. If you need any particular information about those entries you have to use different queries. For example assume the following product table:
+----+-------------+-------------+
| ID | ProductNAme | ProductType |
+----+-------------+-------------+
| 1 | Product A | Type A |
+----+-------------+-------------+
| 2 | Product B | Type A |
+----+-------------+-------------+
| 3 | Product C | Type B |
+----+-------------+-------------+
You can get the quantity of Type A Products by writing the following query (view This Link for a better understanding):
Select count(*) as CountOfProduct from Product where ProductType="Type A";
EDIT
You mentioned in your comment that one product could possibly have different types and different quantities. You can do that in one table but that looks messy. If you want this to happen you need two build a 1-Many **relationship** between two tables called product and type.
The type table could be something like this :
| TYPE_ID | TYPE |
|---------|--------|
| 1 | Type A |
| 2 | Type B |
| 3 | Type C |
and your product table could be something like this:
| PRODUCT_ID | PRODUCTNAME | QUANTITY | TYPE_ID |
|------------|-------------|----------|---------|
| 1 | Product A | 3 | 1 |
| 2 | Product B | 2 | 1 |
| 3 | Product C | 1 | 2 |
| 4 | Product C | 5 | 3 |
**take note that type_id is the foreign key which builds the relation between these two tables. And since you can have multiple products with the same type (like product C in this example) this table will be your many table and type table will be your one table. Hence, with putting the foreign key in the many table you will establish the one to many relationship.
Now, in order to combine (or in other words to join) these two tables you will need to write a join query as following:
select ProductName,quantity,Type from Product p
inner join type t on t.type_id=p.type_id
and the result will be what you want:
| PRODUCTNAME | QUANTITY | TYPE |
|-------------|----------|--------|
| Product A | 3 | Type A |
| Product B | 2 | Type A |
| Product C | 1 | Type B |
| Product C | 5 | Type C |
Check this link out for the fiddle

Related

How to Structure Tables for Product Variation with MySQL [duplicate]

This question already has answers here:
How to design a product table for many kinds of product where each product has many parameters
(4 answers)
Closed 8 months ago.
I need help with Product Variations. I haven't started anything yet, so I don't have an example because I don't know where to start. I will make a small sketch of what I think it should look like, and anyone who has experience with this category would help me a lot.
Database structure:
Color
| id | Color Name | Product ID |
| 1 | White | 1 |
| 2 | Black | 1 |
Size
| id | Size Name | Product ID |
| 1 | XXXL | 1 |
| 2 | M | 1 |
Product
| id | Product Name | Product Size | Product Color | Product Description
| 1 | Jacket | 1,2 | 1,2 | Jacket.....
Because I have never done product variation before, I want to get information on whether this method is correct or not? Share with me your opinions, and experiences on how to do it in the best possible way
Use a mixture of columns and JSON.
The columns should be items that are typically searched on. Index the columns.
The JSON column contains the less common attributes -- For example, only dresses have a "dress size", only cameras have an "F-stop".
Have MySQL search on columns; have the app finish the filtering by checking the JSON.
More: Entity-Attribute-Value

SQL: many-to-many relationship and the 'ALL' clause

I have a table products and a table locations which are linked together in a many-to-many relationship with a table products_locations. Now a client can select a set of products, and I want to run a query that selects only the locations, where ALL of the selected products are available.
This seemed pretty straight forward at first, but I see myself being quite baffled by how to achieve this. I initially thought I could get all the correct location-ids with something like
SELECT location_id
FROM products_locations
WHERE product_id = ALL [the user selected product ids]
But on second thought that does not appear to make sense either (the structure of products_locations is quite simply [product_id, location_id].
Any suggestion on how to structure such a query would be appreciated. I feel like I am overlooking something basic..
EDIT: I am using mysql syntax/dialect
Quick sample: Given the following tables
| products | | locations | | products_locations |
| id | name | | id | name | | product_id | location_id |
|------------| |-----------| |--------------------------|
| 1 | prod1 | | 1 | locA | | 1 | 2 |
| 2 | prod2 | | 2 | locB | | 2 | 1 |
| 3 | prod3 | |-----------| | 2 | 2 |
|------------| | 3 | 1 |
|--------------------------|
If a user selects products 1 and 2, the query should return only location 2. If the user selects products 2 and 3, the query should return location 1. For 1, 2, and 3, no location would be valid, and for product 2, both locations would be valid.
I figured out a query that achieves what I need. Though it is not as clean as I had hoped, it seems to be a robust approach to what I'm trying to query:
SELECT t.location_id
FROM (SELECT location_id, COUNT(*) as n_hits
FROM products_locations
WHERE product_id IN [the user selected products]
GROUP BY location_id) t
WHERE n_hits = [the number of user selected products];
Explanation:
I create a temporary table t which contains every location_id that has at least one matching product in the user's selection, together with the number of times that location matches a product in the user's selection. This is achieved by grouping the query by location_id.
I select the location_id(s) from that temporary table t, where the number of hits is equal to the number of products the user had selected. If that number is lower, I know that at least one product did not match that location.

Difficulty in database design

I am experiencing difficulty in MySQL database design.
I have the following tables:
school_table
id | school_name
---------------------------
1 | success primary school
stage_table
id | stage_name
---------------------------
1 | nursery
2 | primary
3 | secondary
school_stage_table
id | school_id | stage_id
---------------------------
1 | 1 | 1
2 | 1 | 2
school_stage_table is a linking table. This is because there is many to many relationship between school and stage, that is a single school may have many stages, and the same stage may have many schools.
The problem comes here:
Each stage has different attributes, and therefore different attribute values for different schools.
How do I model this scenario in a database? Need your help.
As you previously said that you are having some issues that how to store different attributes of each stage of each schools.
Here you can take one table which will store all the attributes of each stage. You can use following table for storing attributes.
Table :
school_stage_attributes_table
id | school_stage_id | attributes_name | attributes_value
------------------------------------------------------------
1 | 1 | attrib_1 | value_1
2 | 1 | attrib_2 | value_2
One option here would be to create a stage_attribute table containing at least the following four columns:
stage_attribute
id | school_id | stage_id | attribute
Each record in this table would correspond to a single attribute for a single stage, e.g.
1 | 1 | 1 | 'nap time'
2 | 1 | 1 | 'breakfast'
3 | 1 | 3 | 'phys ed'
I suspect that some of the difficulty in your mind was with the possibility of adding attribute columns to the stage_table for each attribute. Of course, this is problematical because each stage could have different numbers or types of attributes, and it won't scale for many attributes. The option I gave above eliminates many of these problems by using an arbitrary number of records to store the stage attribute information.
You should use table school_stage_table for this different attribute values for different schools.
If You will use the same attributes schema for multiple schools, then there should be one more table called for example school_stage_options with fields
school_stage_options_id | stage_id | option1 | option2 ....
and later use school_stage_options_id in school_stage_table instead of using stage_id.

Split SQL field containing array into new table/rows

I need a list of user IDs (course_user_ids) that is currently stored in a single field of a larger table.
I have a table called courses that contains course information with course_id and course_students as such:
-----------------------------------------------------------
| course_id | course_students |
----------------------------------------------------------
| 1 | a:3:{i:0;i:12345;i:1;i:22345;i:2;i:323456;} |
-----------------------------------------------------------
| 2 | a:32:{ … } |
-----------------------------------------------------------
The course_students part contains 3 chunks of information:
the number of students (a:3:{…) -- not needed
the order/key for the array of each student ({i:0;… i:1;… i:2; …}) -- also not needed
the course_user_id (i:12345; … i:22345;… i:32345;)
I only need the course_user_id and the original course_id, resulting in a new table that i can use for joins/subqueries like this:
------------------------------
| course_id | course_user_id |
------------------------------
| 1 | 12345 |
------------------------------
| 1 | 22345 |
------------------------------
| 1 | 323456 |
------------------------------
(ideally able to continue to break out values for other course_ids and course_user_ids, but not a priority:)
| … | … |
------------------------------
| 2 | … |
------------------------------
| 2 | … |
------------------------------
| 97 | … |
------------------------------
| 97 | … |
------------------------------
| … | … |
------------------------------
Note: the course_user_id can vary in length (some are 5 digits, some are 6)
Any ideas would be much appreciated!
Update
My user table does have user_id which can be mapped to course_students or course_user_id, so that is a very helpful observation from below.
I also think I need to use a LEFT JOIN because some students are registered in multiple courses, and I'd like to see each instance/combo.
Let us assume that you have a table name users which contains all users data along with user_id.
Now you can join table courses and table users in following manner:
select c.course_id,u.user_id
from
courses c
join users u
on u.user_id=if(instr(c.course_students,concat(":",u.user_id,";"))>0,u.user_id,c.course_students)
You get the result as per your requirement.
Verify at http://sqlfiddle.com/#!9/3667d/2
Note: The above query works fine if no overlapping between user_id and array index. In case of overlapping, kindly filter data using where-clause
If I got your goal correctly you have users table. And {i:0;i:12345;i:1;i:22345;i:2;i:323456; equal users.id=12345,users.id=22345 etc.
If my guess is correct you can try this solution:
http://sqlfiddle.com/#!9/cfef27/5
SELECT * FROM courses
LEFT JOIN users u
ON courses.course_students LIKE CONCAT('%i:',u.id,';%')

how can we add two field in same column in sql table?

i want to create a database that consists all products rating and notes purchase by user
suppose that i create a table name "Users_rating_product" that consists some column
user_id ->INT
company->Varchar
product1 -> 3 (rating of product out of 5)|(review of product)
product2-> 4(rating)|(some review)
i want to know how can i do it in mysql . i'm using phpmyadmin for database creation
table looks like
user_id | company |Ac | TV | fridge
1 | goderaj |3 ,take more power |4,less power |5,efficient
i want to know how can i do this so that both rating and notes for product display in same column
For this you'll need a separate table. Call it ProductRating. Put a unique key (ID) to the table and reference that key to your Users_rating_product table.
For example:
Users_rating_product:
user_id | company |Ac | TV | fridge
1 | goderaj |1 | 2 | 3
2 | somecomp |4 | 5 | 6
ProductRating
ID | Rating | Review
1 | 3 | Take more power
2 | 4 | less power
3 | 5 | efficient
4 | 5 | excellent
5 | 1 | awful
6 | 3 | average
There are many ways that you can achieve your functionality.
but this is not standard format to write queries.
you can have comma seperated column in your database like this
user_id | company |Ac_mapping_id
1 | goderaj |1,REview for Ac
for Seperate two values you can do like this
PARSENAME(REPLACE(String,',','.'),2) 'Name'
for Detail Reference for splitting two values you can refer :
click To refer
Better Way is to store Product description in different table.
You can easily write queries to retrieve your data
user_id | company |Ac_mapping_id | TV_mapping_id | fridge_mapping_id
1 | goderaj |1 | 2 | 3
& store all the ratings & reviews in mapping table like this
Ac_mapping_id | Rating |Review
1 | 1 |abcd
So on for the other table.
For Retrieving all the data just Use Left outer join
Select
*
from
Users_rating_product mm
Left outer join Ac_mapping_table ac on ac.ac_mapping_id = mm.ac_mapping_id
.....so on