Optimal MySQL table format [closed] - mysql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
In a mysql automotive parts database, which is the optimal table Format?
Scenario 1:
Table 1
ID1 | Make | Model | Type
Table 2
ID2 | Part_description | OEM_code
Connection table
ID | ID1 | ID2
Scenario 2:
Table 1
ID1 | Make
Table 2
ID2 | FK_ID1 | Model
Table 3
ID3 | FK_ID2 | Type
Table 4
ID4 | Part_description | OEM_code
Connection table
ID | ID1 | ID2 | ID3 | ID4
In First scenario, the IDs can be used directry for indicating parts, but there are multiple duplicates in make and model columns.
In Second scenario, 3 IDs need to indicate a part and I think that querying would be faster, but I'm not sure about multiple IDS.
What is your opinion?

In my opinion the data model depends on how you want to use it. Generally it would suffice to have a table per car version:
id | car_version
---+--------------------------
1 | BMW 530i 2019
2 | BMW 530e 2019
3 | BMW 540i 2019
4 | BMW 530i 2020
5 | BMW 530e 2020
6 | BMW 530e iPerformance 2020
7 | BMW 540i 2020
You would show this list sorted by alphabet to pick a car. With a very long list, however, this can become inconvenient. Hence, if you want to drill down to the car version, above table will not be optimal any longer, because you could have typos going unnoticed, like:
VMW 530i 2020
which would be hidden way down the list. So, you'd want a table for the make to avoid this. You can show a list of makes, pick a make, then show a list of models. And as a model can have several versions, you'll have yet another table, so after picking the model you are shown the versions.
table make
make_id | name
--------+-----
1 | BMW
table model
model_id | make_id | name
---------+---------+-----
1 | 1 | 530i
2 | 1 | 530e
table version
version_id | model_id | year
-----------+----------+-----
1 | 1 | 2019
2 | 2 | 2019
3 | 1 | 2020
4 | 2 | 2020
Your parts table would then link a part to a car version:
table part
part_id | part_number | name
--------+-------------+-------------
1 | 1234567 | battery AXX4
2 | 1238867 | battery AXX5
table part_match
part_id | version_id
--------+-----------
1 | 1
1 | 2
1 | 3
2 | 3
2 | 4

Related

how should I build up my database when I want to store these kind of data?

I want to build a page like shown below and all data should be retrieved from a database. Both the term, subject and sentences is retrieved from a database. Three levels of data. And under each term (eg. Spring 2017) I can pick and choose between all of these sentences.
Spring 2017
Subject1
Sentence 1
Sentence 2
Sentence 3
Subject2
Sentence 13
Sentence 12
Sentence 17
Subject3
Sentence 11
Sentence 14
Sentence 19
Autmn 2017
...
I want to present similar info from database to user, and let the user choose between all this sentences. How should i build up my database for achieving this in the best and most efficient way.
One way is:
Table 'subject' Table 'sentences'
| id | subjects | | id | subjectid | name |
| 3 | Subject1 | | 1 | 3 | Sentence 2 |
| 4 | Subject2 | | 2 | 4 | Sentence 13 |
Table 'term'
| id | term | sentenceid |
| 1 | Spring 17 | 1,2,28 |
Another way is maybe using pivot-tables, something like this:
Table 'sentences'
| id | parentid | name |
| 1 | 0 | Subject2 |
| 2 | 3 | Sentence 2 |
| 3 | 0 | Subject1 |
| 4 | 1 | Sentence 13 |
Table 'term'
| id | term | sentenceid |
| 1 | Spring 17 | 2,4,28 |
Notice: Number of terms can be many more than just two in a year.
Is it any of this structures you recommend, or any other way you think I should build my database? Is one of these more efficient? Not so demanding? Easier to adjust?
You are doing relational analysis/design:
Find all substantives/nouns of your domain. These are candidates for tables.
Find any relationships/associations between those substantives. "Has", "consists of", "belongs to", "depends on" and so on. Divide them into 1:1, 1:n, n:m associations.
look hard at the 1:1 ones and check if you can reduce two of your original tables into one.
the 1:n lead you to foreign keys in one of the tables.
the n:m give you additional association tables, possibly with their own attributes.
That's about it. I would strongly advise against optimizing for speed or space at this point. Any modem RDBMS will be totally indifferent against the number of rows you are likely to encounter in your example. All database related software (ORMs etc.) expect such a clean model. Packing ids into comma separated fields is an absolutes no-no as it defeats all mechanisms your RDBMS has to deal with such data; it makes the application harder to program; it confuses GUIs and so on.
Making weird choices in your table setup so they deviate from a clean model of your domain is the #1 cause of trouble along the way. You can optimize for performance later, if and when you actually get into trouble. Except for extreme cases (huge data sets or throughput), such optimisation primarily takes place inside the RDBMS (indexes, storage parameters, buffer management etc.) or by optimizing your queries, not by changing the tables.
If the data is hierarchical, consider representing it with a single table, with one column referencing a simple lookup for the "entry type".
Table AcademicEntry
================================
| ID | EntryTypeID | ParentAcademicEntryID | Description |
==========================================================
| 1 | 3 | 3 | Sentence 1 |
| 2 | 1 | <null> | Spring 2017 |
| 3 | 2 | 2 | Subject1 |
Table EntryType
================================
| ID | Description |
====================
| 1 | Semester |
| 2 | Subject |
| 3 | Sentence |
Start with the terms. Every term has subjects. Every subject has sentences. Then you may need the position of a subject within a term and probably the position of a sentence in a subject.
Table 'term'
id | term
---+------------
1 | Spring 2017
Table 'subject'
id | title | termid | pos
---+----------+--------+----
3 | Subject1 | 1 | 1
4 | Subject2 | 1 | 2
5 | Subject3 | 1 | 3
Table 'sentence'
id | name | subjectid | pos
---+-------------+-----------+-----
1 | Sentence 2 | 3 | 2
2 | Sentence 13 | 4 | 1
3 | Sentence 1 | 3 | 1
4 | Sentence 3 | 3 | 3
2 | Sentence 17 | 4 | 3
...
This table design Should resolve your need.
TblSeason
(
SeasonId int,
SeasonName varchar(30)
)
tblSubject
(
Subjectid int
sessionid int (fk to tblsession)
SubjectData varchar(max)
)
tblSentences
(
SentencesID INT
Subjectid int (Fk to tblSubject)
SentenceData varchar(max)
)

Access table design

I have the following requirement for an Access table and I'm having trouble figuring out the best way to design the table. I'm not sure if what I have is the best practice in this case.
table fields are name, Status, Date
each name will have minimum three status, and they change every month and then stop at Open. the date for each status change has to be captures in the database.
Example :
Name | Status | Date
--------+-----------+------------------
name1 | N/A | April
name2 | N/A | April
name1 | Open | May
name2 | N/A | May
name1 | closed | June
name1 | open | July
From the normalized point of view you need 4 tables total
1st table the master table
Name | Status | Date (month ?)
--------+-----------+--------
1 | 1 | 4
2 | 3 | 5
2nd table the names table
ID | Names
--------+-----------
1 | name1
2 | name2
3rd table status table
ID | Status
--------+-----------
1 | N/A
2 | Open
3 | closed
4th table Months
ID | Month
--------+-----------
1 | January
2 | February
........|............
12 | December
Honestly I have thought about this particular setup a number of times myself. I inherited a database that uses the format that you have posted.
While I don't think that setup is bad, another idea that I had was to create 3 checkbox fields that belong to each status to show progress. Then there would be 3 date fields, each one pertaining to when the checkbox was checked off.
That would cut the number of records down by 2/3rds but again. I think it is more of a matter of opinion.

How to store multiple values in single column where use less memory?

I have a table of users where 1 column stores user's "roles".
We can assign multiple roles to particular user.
Then I want to store role IDs in the "roles" column.
But how can I store multiple values into a single column to save memory in a way that is easy to use? For example, storing using a comma-delimited field is not easy and uses memory.
Any ideas?
If a user can have multiple roles, it is probably better to have a user_role table that stores this information. It is normalised, and will be much easier to query.
A table like:
user_id | role
--------+-----------------
1 | Admin
2 | User
2 | Admin
3 | User
3 | Author
Will allow you to query for all users with a particular role, such as SELECT user_id, user.name FROM user_role JOIN user WHERE role='Admin' rather than having to use string parsing to get details out of a column.
Amongst other things this will be faster, as you can index the columns properly and will take marginally more space than any solution that puts multiple values into a single column - which is antithetical to what relational databases are designed for.
The reason this shouldn't be stored is that it is inefficient, for the reason DCoder states on the comment to this answer. To check if a user has a role, every row of the user table will need to be scanned, and then the "roles" column will have to be scanned using string matching - regardless of how this action is exposed, the RMDBS will need to perform string operations to parse the content. These are very expensive operations, and not at all good database design.
If you need to have a single column, I would strongly suggest that you no longer have a technical problem, but a people management one. Adding additional tables to an existing database that is under development, should not be difficult. If this isn't something you are authorised to do, explain to why the extra table is needed to the right person - because munging multiple values into a single column is a bad, bad idea.
You can also use bitwise logic with MySQL. role_id must be in BASE 2 (0, 1, 2, 4, 8, 16, 32...)
role_id | label
--------+-----------------
1 | Admin
2 | User
4 | Author
user_id | name | role
--------+-----------------
1 | John | 1
2 | Steve | 3
3 | Jack | 6
Bitwise logic allows you to select all user roles
SELECT * FROM users WHERE role & 1
-- returns all Admin users
SELECT * FROM users WHERE role & 5
-- returns all users who are admin or Author because 5 = 1 + 4
SELECT * FROM users WHERE role & 6
-- returns all users who are User or Author because 6 = 2 + 4
From your question what I got,
Suppose, you have to table. one is "meal" table and another one is "combo_meal" table. Now I think you want to store multiple meal_id inside one combo_meal_id without separating coma[,]. And you said that it'll make your DB to more standard.
If I not getting wrong from your question then please read carefully my suggestion bellow. It may be help you.
First think is your concept is right. Definitely it'll give you more standard DB.
For this you have to create one more table [ example table: combo_meal_relation ] for referencing those two table data. May be one visible example will clear it.
meal table
+------+--------+-----------+---------+
| id | name | serving | price |
+------+--------+-----------+---------+
| 1 | soup1 | 2 person | 12.50 |
+------+--------+-----------+---------+
| 2 | soup2 | 2 person | 15.50 |
+------+--------+-----------+---------+
| 3 | soup3 | 2 person | 23.00 |
+------+--------+-----------+---------+
| 4 | drink1 | 2 person | 4.50 |
+------+--------+-----------+---------+
| 5 | drink2 | 2 person | 3.50 |
+------+--------+-----------+---------+
| 6 | drink3 | 2 person | 5.50 |
+------+--------+-----------+---------+
| 7 | frui1 | 2 person | 3.00 |
+------+--------+-----------+---------+
| 8 | fruit2 | 2 person | 3.50 |
+------+--------+-----------+---------+
| 9 | fruit3 | 2 person | 4.50 |
+------+--------+-----------+---------+
combo_meal table
+------+--------------+-----------+
| id | combo_name | serving |
+------+--------------+-----------+
| 1 | combo1 | 2 person |
+------+--------------+-----------+
| 2 | combo2 | 2 person |
+------+--------------+-----------+
| 4 | combo3 | 2 person |
+------+--------------+-----------+
combo_meal_relation
+------+--------------+-----------+
| id | combo_meal_id| meal_id |
+------+--------------+-----------+
| 1 | 1 | 1 |
+------+--------------+-----------+
| 2 | 1 | 2 |
+------+--------------+-----------+
| 3 | 1 | 3 |
+------+--------------+-----------+
| 4 | 2 | 4 |
+------+--------------+-----------+
| 5 | 2 | 2 |
+------+--------------+-----------+
| 6 | 2 | 7 |
+------+--------------+-----------+
When you search inside table then it'll generate faster result.
search query:
SELECT m.*
FROM combo_meal cm
JOIN meal m
ON m.id = cm.meal_id
WHERE cm.combo_id = 1
Hopefully you understand :)
You could do something like this
INSERT INTO table (id, roles) VALUES ('', '2,3,4');
Then to find it use FIND_IN_SET
As you might already know, storing multiple values in a cell goes against 1NF form. If youre fine with that, using a json column type is a great way and has good methods to query properly.
SELECT * FROM table_name
WHERE JSON_CONTAINS(column_name, '"value 2"', '$')
Will return any entry with json data like
[
"value",
"value 2",
"value 3"
]
Youre using json, so remember, youre query performance will go down the drain.

How to update a 'Sort Index' column of a list of records with one call

Basically, I have a list of records in a mysql db. These records are ordered 1 to 10. The user can re-order these records to whatever order they want. They will press a button to update all the records to their newly, respective order number. For example:
ID | Sort_Index | Name
----------------------
1 | 1 | Jim
2 | 2 | Bob
3 | 3 | Carl
4 | 4 | Bill
5 | 5 | Wendy
The user can change these to this for example:
Note: the changed values are stored into an array before I make the UPDATE calls
ID | Sort_Index | Name
----------------------
1 | 1 | Carl
2 | 2 | Wendy
3 | 3 | Bob
4 | 4 | Jim
5 | 5 | Bill
My question is, how can I make this mysql call with one call, using the new values in my array, instead of one call for each record?
If this is impossible or simply the "wrong way to do it", please feel free to suggest new ideas as I am not fully committed to this idea as of now.
If you have a limited number of rows, you could implement this with an sql CASE statement --
Update users set sort_index = case id when 1 then <newval> when 2 then <newval>...

SQL query to find category and sub category

I have a table which have category_id and parent_category_id. How I can get 1 category and 5 sub category by using SQL query.
Suppose table name is : Category
----------------------------------------------------------------
Category ID | Parent ID | Name
----------------------------------------------------------------
1 | NULL | Electronics
2 | 1 | Computer
3 | 1 | Calculator
4 | 1 | Mobile
5 | NULL | Four Wheeler
6 | 5 | Cars
7 | 5 | Trucks
8 | 5 | Jeep
9 | 5 | Van
Since MySQL does not support recursive queries/CTEs, you will have to emulate that (which is not, say, straightforward).
Here's an excellent tutorial on the subject:
http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/
I will have the decency of not copying the code here :)
For SQL Server, you can use the WITH query to get the complete path (more here http://msdn.microsoft.com/en-us/library/ms175972.aspx).