I have the following relationships:
order_products (1 or n) ———————— (1) orders (1) ————————— (1) transactions
... (1) (1)
price | |
qty | |
(1) (1)
users users
Should I leave 2 relationships to users table as above?
I intend to show the total order amount or get the transaction amount will query the order_products table. This is better than adding the amount field at 1 of two tables (or both) orders, transactions?.
Start by deciding which relationship exists in each case:
1-1 -- the two tables should probably be merged together.
1:many -- the "many" table has a column with the ids into the "one" table.
many:many -- This needs an extra table with 2 ids (one for each table).
Related
Table order_detail:
order_no | product_id
Table product_detail:
prod_id | prod_name | prod_size | prod_type
order_detail .product_id references to product_detail.prod_id
I heard data redundancy is a bad idea, so I inner join the tables to display the complete order details. But the problem is the data inside product_detail can be edit or delete by admin, which means when I inner join the tables, it might return null. Should I store something like JSON example: {size:23,type:MZ} in the order_detail to avoid the data 'loss'?
You will need to break down your table structure.
Having to store data in JSON format in your order_detail table compromises normalization on your database(which is not desirable).
Make product attributes as individual entities.
Product_detail
id | name | some_other_descriptive_columns | deleted_at
Product_Type:
id | type
Product_size:
id | size
Product_type_mapping:(pivot table which signifies many-to-many relationship between products and it's types)
id | product_id | product_type_id | deleted_at
Product_size_mapping:(pivot table which signifies many-to-many relationship between products and it's sizes)
id | product_id | product_size_id | deleted_at
As you might have already noticed, we have an additional column called deleted_at whose datatype will be a timestamp and which is nullable by default in all the tables shown above.
When the admin edits(could also be removal of certain sizes or types) or deletes a product, all we do is make an entry of a timestamp in deleted_at column. In other words, we do a soft delete.
So, when the admin operates on a product data set, fetch all the details whose deleted_at column IS NULL. When doing an inner join to fetch order details, it would not hinder the process of losing any data even if admin deletes a product after a few days after an order was made, because we would fetch all details regardless of what we have in our deleted_at column.
I suggest that you consider using a schema like the one in the diagram. (The arrowheads are the "many" end of the PK-FK relationships.)
This approach maintains referential integrity and avoids the use of nulls by recording deletions in a separate table.
You might also want to add a "ProductDataChangedOnDate" feature that keeps a record of the changes made by that pesky admin person :-)
While using mysql workbench and for designing database using designer the relation tool uses a third table to form a many to many relation between 2 tables.
I have 3 tables
TABLE1
TABLE2
TABLE3
TABLE2 has foregin key from primary key of TABLE1,having a many to one relation
TABLE2 and TABLE3 are related using a many to many relation,
as soon as I create the relation
a new table TABLE3_has_TABLE2 is created with all the key from TABLE2(primarykey of table2 & foreign key of table1) and TABLE3 (primary key of table3).
Now,
why is there foreign key of table1.?
Even if i remove I will be able to query data from table1 and table3 using table2 as intermediate, so is it good to have this kind of relation or avoided?
For Example in below diagram
This is a geographical distribution of location, on right side it shows the hirarchy.
Now,
Table1(Zone) is the primary table i.e Zone
Table2(state) is related to table1 using zone_id
Table3(division) is related to table2(state) using state_id & zone_id of table1(zone)
Question: Should this zone_id column be in the table3 or not?
similarly table4 contains all the previous key columns of table3.
Strictly from a denormalization point-of-view, the DIVISION.STATE_ZONE_ID isn't required.
Since you can get the ZONE_ID from the DIVISION by joining STATE on the state_id.
And it's the same with the division_state_state_id & division_state_zone_id in DISTRICT.
Having the division_division_id is enough to join DIVISION, then STATE, then ZONE.
However, what if you would remove those 'extra' fields?
Then a SQL always needs to go through that cascade of joined tables to get the ZONE.zone_name.
So there's an advantage that by having those 'extra' fields, it becomes possible to JOIN directly to the ZONE table. Which can simplify/speed up certain popular queries.
The disadvantage is that it becomes harder to assure referential integrity.
Because for example, you could assign a different zone_id to a DIVISION.state_zone_id than the STATE.zone_id you can get via DIVISION.state_state_id.
It is best practice in relational models to avoid many-to-many relationships. Workbench usually compensates for user trying to do that as you have seen.
Let us use an example (or check the tl;dr), where there are two identified entities; buyers and hardware items. Some people buy 1 item, others buy more than one. The thing is, that same item can be bought by many people. So the buyer table has Mr. A buying nails. Simple enough to record in one row. But lo' and behold, he ups and gets another item! How do we show that he buys another item?
One way is by adding another attribute to the table (say "item_number_two"). But then he gets another! We can't keep going adding attributes like that. Databases were designed more for vertical addition of records, rather than horizontal addition of attributes (to give a visual picture). There is a longer explanation but you should read up, or probably might figure it out after reading this.
Another way is to re-enter a record for Mr. A and then put the ID of another item in that column, showing that he bought two items (not really "he" from a database stand-point, it's two different people!).
A better method would be to create a table that consists of the unique identifiers found in the original tables (just one per table may be necessary). This is called an intermediary table. The original tables themselves do not have foreign keys from the other table.
This is where the concept of a composite key comes in. It means that two or more candidate keys are used to uniquely identify a record rather than just one. This is how it works:
Person Table:
| person_ID | person_Name |
| P0001 | Mr. A |
| P0002 | Mr. B |
| P0003 | Mr. C |
| P0004 | Mr. D |
Cat Table
| item_ID | cat_Name |
| I0001 | Nails |
| I0002 | Screws |
| I0003 | Hammers |
| I0004 | Power-Saw |
Intermediary table
| person_ID | item_ID |
| P0001 | I0001 |
| P0001 | I0002 |
| P0001 | I0003 | //Shows that person 1 bought more than one item
| P0002 | I0004 |
| P0002 | I0001 | //Shows that an item has been bought by more that one person
So this new table matches a record of one table(through the use of a primary key) to a record of another. The only thing that will ever be repeated is one of the two ID's. A unique record is made as long as no two combinations are repeated.
tl;dr - Having tables mapped in a many to many relationship inevitably wastes space in the DB when entering records, as new records of the same data have to be made to show a small difference (adding no real value in proportion to the space). Another issue is that it causes more calculations than necessary when a query is made, wasting time and space. Or the results returned may just be plain wrong...
EDIT:
If you have tables A and B having a many-to-many relationship, do the following as an alternative. Create a table C. Take the primary keys from table A and B and place them in tables C. In table C they both exist as primary and foreign keys. This would mean the following relationship is created.
| Table A |-----------<| Table C |>------------|Table B|
Table A and B are linked through C.
Sample query:
SELECT C.itemID FROM A, C WHERE A.personID = P0001 AND A.personID = C.personID;
This query will return all ID's of the items bought by the person with an ID of P0001. Records must match the condition of having a personID of P0001, but the record selected must have that matching ID in Table C (the intermediary table). An extended query could be to take the item names from the Table B. Each attribute in C has a recorded value that corresponds to a value of a key in either Table A or B, meaning that a query can be run to pull other info, where the value in Table C is = to the values in Table A/B (depending on which one you want).
I need help to design a table for Restaurant Point of Sales System particularly in merging and unmerging restaurants table.
For example, i want to merge tables 1-3 as Table 1,
-Table 1
-Table 2
-Table 3
Table 4
Table 5
Then it would be something like this,
Table 1
-Table 1
-Table 2
-Table 3
Table 4
Table 5
After a transaction the tables can be unmerge. Anyone who has a solution to this?
To expand on what zerkms suggests, you will want a two-tiered system to support this approach. Link table information (server, order, timing, etc) to a Seating. Seating will have a one-to-many relationship with a Table relation.
When a guest is assigned to a single table, one Table will be linked to one Seating. If a group of guests is assigned to multiple tables, multiple Tables will be linked to a single Seating.
When a group of guests leaves, unlink their Tables from their Seating. To count unused tables, simply COUNT entries from Table.
- Seating 1
- Table 1
- Seating 2
- Table 2
- Table 3
- Table 4
Note: Table entries will be static for the lifetime of the restaurant (unless more physical tables are added). Seating entries should be dynamically created and removed as necessary.
I have two entities Invoice and User.
Invoice have following relations with user
invoice have a owner(one to one relation with user)
one invoice can share with multiple users, it means invoice can have multiple shared users(one to many relation with user)
How to map these relations in mysql database? how many tables? and table structure?
invoice could have two fields, billed_to and payed_by. your billed_to field would be your one to one relationship, and the payed_by field would be your one to many.
For One-to-one relationship, it is advised not to keep separate table. Keep it with the invoice table itself.
For one-to-many relationship, keep another mapping table.
Your table structure should be
Users
----------
id | xxx | .....
-
Invoices
------------
id | user_id | .....
in the above case user_id is the owner.
shared_invoices
-------------------
id | user_id | invoice_id
I have a mysql table that stores user ratings for different items. It has the following fields:
id (int, pk)
userId (int)
itemId (int)
rating (float)
timestamp (int)
and following indices:
(userId, rating): for queries about all items a particular user has rated
(itemId, rating): for queries about all users that have rated a particular item
This table has over 10 million rows. To make it more scalable, I would like to perform a horizontal partitioning. In particular, I plan to partition the table into 20 tables:
tbl_rating_by_item_0: store ratings whose itemId ending with 0
tbl_rating_by_item_1: store ratings whose itemId ending with 1
......
tbl_rating_by_item_9: store ratings whose itemId ending with 9
and
tbl_rating_by_user_0: store ratings whose userId ending with 0
tbl_rating_by_user_1: store ratings whose userId ending with 1
......
tbl_rating_by_user_9: store ratings whose userId ending with 9
The idea is when querying by itemId we read from tbl_rating_by_item_itemId and when querying by userId we read from tbl_rating_by_user_userId. The drawback is whenever I want to insert or delete a rating, I need to insert into or delete from two tables.
Is there any other solutions?
Have you tried indexing? Creating two composite indexes
INDEX name1 (rating,userid)
INDEX name2 (rating,itemId)
may help increase in performance.
Also consider table partitioning. Have a look at Mysql able partitioning
This is better than physically creating two separate tables.