How to design a MySQL database for storing sell items - mysql

I have been trying to design a MySQL table o store the items of the store purchased by the costumers. I am stuck with what approach should I take to design a good table.
My first option is:
id
bill_id_fk
item1_id
item2_id
item3_id
item4_id
In this approach, I'll create may be 20 columns for items (assuming that a costumer may buy a maximum of 20 items at a time). ID of the items will be stored in the item(n)_id columns for that specific bill_id_fk.
My concern with this approach is that it would be difficult to query later for a specific item, like how many times a specific item has been sold.
My second opinion is:
id
bill_id_fk
item_id
1
1
23
2
1
29
3
2
23
In this approach, I'll just create 3 columns and for each item I'll create a rows with the bill_id_fk for a specific bill.
In this approach, it is easier to query for a counts of the sell of a specific item. But my concern is creating thousands and thousands of rows when the app will be used and how will that affect the performance of the app over time?
I'd like to have your opinion on what is the best practice for designing such database. Or is there any other approach should I take?

There's no chance that you will go with the first choice, the second is the best approach for your case.
it will not affect your performance if you indexed the right columns.
When it comes to items can add a column to your bills table that holds item numbers, for example:
bills (id - total_price - user_id - item_counts)
bill_items (id - bill_id - item_id - item_price)

Related

MySQL query performance with reference tables

For the following 2 tables structures, assuming the data volume is really high:
cars table
Id | brand name | make year | purchase year | owner name
Is there any query performance benefit with structuring it this way and joining the 2 tables instead?
cars table
Id | brand_id | make year | purchase year | owner name
brands table
Id | name
Also, if all 4 columns fall in my where clause, does it make sense indexing any?
I would at least have INDEX(owner_name) since that is very selective. Having INDEX(owner_name, model_year) won't help enough to matter for this type of data. There are other cases where I would recommend a 4-column composite index.
"data volume is really high". If you are saying there are 100K rows, then it does not matter much. If you are saying a billion rows, then we need to get into a lot more details.
"data volume is really high". 10 queries/second -- Yawn. 1000/second -- more details, please.
2 tables vs 1.
Data integrity - someone could mess up the data either way
Speed -- a 1-byte TINYINT UNSIGNED (range 0..255) is smaller than an average of about 7 bytes for VARCHAR(55) forbrand. But it is hardly enough smaller to matter on space or speed. (And if you goof and makebrand_idaBIGINT`, which is 8 bytes; well, oops!)
Indexing all columns is different than having no indexes. But "indexing all" is ambiguous:
INDEX(user), INDEX(brand), INDEX(year), ... is likely to make it efficient to search or sort by any of those columns.
INDEX(user, brand, year), ... makes it especially efficient to search by all those columns (with =), or certain ORDER BYs.
No index implies scanning the entire table for any SELECT.
Another interpretation of what you said (plus a little reading between the lines): Might you be searching by any combination of columns? Perhaps non-= things like year >= 2016? Or make IN ('Toyota', 'Nissan')?
Study http://mysql.rjweb.org/doc.php/index_cookbook_mysql
An argument for 1 table
If you need to do
WHERE brand = 'Toyota'
AND year = 2017
Then INDEX(brand, year) (in either order) is possible and beneficial.
But... If those two columns are in different tables (as with your 2-table example), then you cannot have such an index, and performance will suffer.

Storing csv in MySQL field – bad idea?

I have two tables, one user table and an items table. In the user table, there is the field "items". The "items" table only consists of a unique id and an item_name.
Now each user can have multiple items. I wanted to avoid creating a third table that would connect the items with the user but rather have a field in the user_table that stores the item ids connected to the user in a "csv" field.
So any given user would have a field "items" that could have a value like "32,3,98,56".
It maybe is worth mentioning that the maximum number of items per user is rather limited (<5).
The question: Is this approach generally a bad idea compared to having a third table that contains user->item pairs?
Wouldn't a third table create quite an overhead when you want to find all items of a user (I would have to iterate through all elements returned by MySQL individually).
You don't want to store the value in the comma separated form.
Consider the case when you decide to join this column with some other table.
Consider you have,
x items
1 1, 2, 3
1 1, 4
2 1
and you want to find distinct values for each x i.e.:
x items
1 1, 2, 3, 4
2 1
or may be want to check if it has 3 in it
or may be want to convert them into separate rows:
x items
1 1
1 2
1 3
1 1
1 4
2 1
It will be a HUGE PAIN.
Use atleast normalization 1st principle - have separate row for each value.
Now, say originally you had this as you table:
x item
1 1
1 2
1 3
1 1
1 4
2 1
You can easily convert it into csv values:
select x, group_concat(item order by item) items
from t
group by x
If you want to search if x = 1 has item 3. Easy.
select * from t where x = 1 and item = 3
which in earlier case would use horrible find_in_set:
select * from t where x = 1 and find_in_set(3, items);
If you think you can use like with CSV values to search, then first like %x% can't use indexes. Second, it will produce wrong results.
Say you want check if item ab is present and you do %ab% it will return rows with abc abcd abcde .... .
If you have many users and items, then I'd suggest create separate table users with an PK userid, another items with PK itemid and lastly a mapping table user_item having userid, itemid columns.
If you know you'll just need to store and retrieve these values and not do any operation on it such as join, search, distinct, conversion to separate rows etc. etc. - may be just may be, you can (I still wouldn't).
Storing complex data directly in a relational database is a nonstandard use of a relational database. Normally they are designed for normalized data.
There are extensions which vary according to the brand of software which may help. Or you can normalize your CSV file into properly designed table(s). It depends on lots of things. Talk to your enterprise data architect in this case.
Whether it's a bad idea depends on your business needs. I can't assess your business needs from way out here on the internet. Talk to your product manager in this case.

How do I structure MySQL tables where one field could contain multiple values (but might not)?

I'm designing a web app which allows users to attend events and search for specific types of events.
Say, for instance, that these events are taking place in Hogwarts. The students have their own table where their studentID is held as a primary key, and this also contains which house they are a part of (of which there are 4), the subject they take, and which year of study they are in (e.g. 1 or 4 or 5, etc). The events can be for all students, specifically for 4th year students in the Ravenclaw house, or anywhere in between.
The events are held in an events table, which contains an eventID as the primary key, but I'm not sure how to hold the data for the house/year/subject it is aimed at. Obviously if an event were only aimed at 3rd year Hufflepuffs who take Potions, or something similarly specific, I could hold it within the same table. However, what if the event is for any year of Hufflepuffs (and not any Slytherins, etc)? Or if all students from all years, houses and subjects are eligible to attend? Will I need a table which holds all the years for each event and a separate table for which houses it's for and a further separate table for the subject it's aimed at?
Any advice or links are appreciated.
I think there are two ways but you definitely need at least one more table for the associations. Either you want to be very specific, about the combinations possible or you want to do it generally, like: only third years, only hufflepuffs, then the combination of the two values will be only third year hufflepuffs.
What I am trying to say are these two options.
1) One table that holds rows with very specific details:Event ID and the explicit combinations of all possible options (Here you will have a lot of rows)
This would mean that the event can be associated with second and third year hufflepuffs, but only second year slytherins.
association_id event_id year_id house_id subject_id
1 1 second hufflepuff potions
2 1 third hufflepuff potions
3 1 second slytherin potions
2) One table per property (here the disctinction is not as clear but you only have to create one row per property etc.
The following two tables could be used to store that all hufflepuffs and all slytherins that are in second or third year might attend
association_id event_id year_id
1 1 second
2 1 third
association_id event_id house_id
1 1 hufflepuff
2 1 slytherin
Does that answer your question or at least help you to find a solution?
Mybe if you can describe the target you are aiming at more closely one can find a solution suitable for your Problem together.

What table structure would best fit this scenario?

I am developing an evaluation system for different programs that needs a lot of flexibility. Each program will have different things to track, so I need to store what data points they want to track, and the corresponding data for the person being evaluated on the particular data point. I am guessing several tables are appropriate. Here is a general outline:
Table: accounts
- unique ID assigned to each account. We'll call this 'aid'
Table: users
- each user with unique ID.
Table: evaluation
- each program will enter in the metrics they want to track into this table (i.e attendance)
- column 'aid' will correspond to 'aid' in account table
Table: evaluation_data
- data (i.e attendance) entered into this database
- column 'aid' will correspond to 'aid' in account table
- column 'uid' will correspond to 'uid' in user table
The input form for evaluation_data will be generated from what's in the evaluation table.
This is the only logical way I can think of doing this. Some of these tables will be growing quite large over time. Is this the most optimal way of doing this?
I'm a little confused about how accounts, users and programs all relate to each other and whether or not account and program are the same thing and that you used the terms interchangeably. I'm going to use different terms which are just easier for me to understand.
Say you have a website that allows freelancers to keep track of different projects and they can create their own data to track. (Hope you see the similarity)
Tables...
freelancers
id title etc
projects
id freelancer_id title description etc
data_options
id freelancer_id title
You can even add other columns like data_type and give options like URL, email, text, date, etc which can be used for validation or to help format the input form.
example data:
1 5 Status
2 5 Budget
3 5 Customer
4 99 Job Type
5 99 Deadline
6 102 Price
7 102 Status
8 102 Due By
This display 3 different freelancers tracking data, freelancers with the id's 5, 99, and 102. Deadline and Due By are essentially the same but freelancers can call these whatever they want.
data_values
id project_id option_id option_value
a column freelancer_id as you would be able to to a join and get the freelancer_id from either the project_id or the option_id
example data:
1000 1 2 $250
1001 1 1 Completed
1002 1 3 Martha Hayes
This is only showing information freelancer with the id 5 has input because option_id's 1-3 belong to that user.

Mysql database design in a many to many relationship

I am designing a database which relates products and the stores which carry them.
Many of the stores will carry the same products as each other.
As well, obviously, there will be many types of products per store.
I tried to do some research on the best way to make the table but all the resources i read online are so technically exhausting and logically formalized that it takes away from ability to intuitively understand what they're saying.
I keep hearing people say that you should use a junction table, but I dont understand how that would be applicable in my case.
What i wanted to do was create one row for "Store" category, and then have separate rows "product_1", "product_2" "product_x" etc. where i would list each of the products the store sells, but i'm not sure if that's good form.
Furthermore, some stores might have 50 products, meaning i would need 50 rows. I'm not sure if there's a way around this or not.
Ultimately, my question is, by standard conventions, what is the ideal database structure for this kind of relationship?
I would have three tables. One for stores [name, id & info]. One for items [name, id & info]. One to link the two [relation id, store id & item id].
This would enable you to change store and item data without having to update your relationships table.
Thus if you want items in a store you search the relation table for items that match the store id. Vice versa if you want stores that have an item, you search the relation table for the item id and return the store id's that carry that item.
Bare necessities Example:
STORE:
*********************
storeID storeName
*********************
1 store1
2 store2
3 store3
ITEMS:
*********************
itemID itemName
*********************
1 item1
2 item2
3 item3
RELATIONS:
*********************
storeID itemID
*********************
1 1
1 2
2 1
2 3
3 2
3 3
Thus to find which items store1 has you would get the storeID which is 1, and search the relations table to find which rows have a store ID = 1, which would return rows one and two, which tells you that store1 has items 1 and 2. Similarly to find which stores cary item2 you would get the ID of item2, which is 2, search the relations table for itemID = 2, which would return rows two and five, which tells you that stores 1 and 3 have item2.