How to design erd where employee is a customer too? [closed] - mysql

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I have a scenario of a movie theatre and in this scenario an employee can be a customer too (because they can buy tickets).
I created two entities, customer and employee. If I make emp_id of employee a foreign key in customer then it makes an employee a customer too:
Customer: cust_id, Name, age, emp_id
Employee: emp_id, Name, age
But when I do this, data of employee gets repeated in customer. What should I do??

First thing when I look at your tables, you shouldn't really store age. Store birthdate or birth year, so that you won't have to update it every year, because age is relative to current year.
Please read on, or skip to TL;DR part if you want my opinion about this.
For the issue you are having there can be multiple design choices and I find it primarily opinion based on which one to choose from.
One option would be to create one table for storing person-related data and include type of the person in this table, so that you will either have customers or employees. This way, your employee can also be treated as a customer, but you know that it's a special one. This way you can convert record of an employee to a customer when he/she is no longer an employee.
Another way to approach this is to treat them as you already have it and deal with the fact that you are repeating data. Unless you have a large amount of employees (this should not be the case for movie theatre) this is a valid approach as well, since obviously they can be customers, but I assume you would like to discount them or for some reason distinguish between those two types of clients.
Like to keep it the way it currently is, but don't want to repeat the data in order not to make mistakes? Alter columns which are shared for both tables and make them nullable. Use trigger or some other rule mechanism to check if emp_id is filled and then keep all other common column values null. This way though you will need to take care of pulling the data from additional table, so a LEFT JOIN is required here to pull the data about customers which are also employees.
And there are much more to choose from ...
TL;DR
If you ask me, I'd most likely go with first option to store person-related data within one table and either create a type of person or have different tables for employees and customers which will be in 1:1 relation with person table.
That said, it could look like:
Person (person_id, name, birth_year)
Employee (person_id, ...) (store only employee related data here)
Customer (person_id, ...) (store only customer related data here)
As a side note, it might be a good idea to figure out how do you want to differentiate people in general. You have not presented scope for the entire system, so it's hard to give some advices around that.

If there is only two roles of customer and employee, you can use one table to store the users, like this:
person(id, name, birth, is_customer, is_employee, ...)
But if you consider more extension in the future, you can add a role table, like this:
role(id, name, ...)
person(id, name, birth, roles, ...)
the column roles can store with json data like [1,2] or string like 1,2, it depends what you like and mysql version.

Related

How to design this one to many database?

I've been doing some reading on 'one to many' databases but I'm struggling understand the best way to implement a solution in my case.
I want a MySQL database to record which employees have read certain training hand-outs at work.
So I have a table of Employees. And I have a table of Hand-outs.
I want to record if the Employee has clicked to say they've read the hand-out.
My Employee table has ID, Name, Email.
My Hand-out table has ID, Title
Am I better adding a field to the Employee table that will contain a list of "Hand-out IDs" to show which hand-outs they've read?
I need to be able to easily search to show what percentage of Employees have read a particular hand-out and I think my method would make that very difficult?
I can't have separate fields on the Employee table such as Handout1, Handout2 etc as new hand-outs will be added regularly.
I'm sure this must be a common problem so wondered if someone could direct me to the best solution for this?
Thanks
I think you need a bridge table here which records relationships between employee and hand-out records. Something like this:
Employee_Handout (ID, EmployeeID, HandoutID)
Every time a new handout comes out, you would insert a record into the handout table. Then, when a given employee reads that handout, you would insert a new record into the Employee_Handout table. You probably don't need to persist non-reads, since they could easily be detected as being absent from the bridge table.
The primary key for this column would probably be (EmployeeID, HandoutID), assuming you would only want a single record relating an employee reading a given handout. This would also mean that a given employee/handout relationship could only be persisted once.

How to manage entity duplication in database table [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last month.
Improve this question
I am working on a simple database design of an application.
I have a Book Illustrator and Editor table.
Modelling 1 Relation between
With this model, I think here is the duplication of the column name in each author editor and illustrator table.
What if a book author, illustrator and editor person are same, in this case, data get duplicated across 3 tables.
But in case of searching it will be faster, I guess as it no of items per table will be less.
Modelling 2
With this modeling, all the author, illustrator and editor info get saved in a single table and I am confused what should be the name of this table.
With this approach. The data won't' get duplicated but the searching will be double as compared to model 1.
Can anyone suggest me which model should I choose. I feel modeling 2 is better.
It is purely up to your taste which model you should use. The second one has the advantage that you wont get duplicates. With both models you can get the results with one query
select * from books
left join names auth ON (auth.id = author_id)
left join names ill ON (ill.id = illustrator_id)
left join names ed ON (ed.id = editor_id)
where books.id = 1;
SQLFiddle gives an example of model 2. If you want to obtain the data from model one, just change the 3 joins to the right table.
If you want to display a list of authors, I would not recommend adding it as a new field in the names table, but just use a joint query.
select auth.* from books
left join names auth ON (auth.id = author_id)
As long as you set the indexes on the id, author_id, illustrator_id and editor_id, you are fine.
Edit: my preference would go to model 2. I think it might also a bit faster:
The database only needs to open one file (not 3)
There are less records in the table (compared to the combined of the 3 tables) because you don't have duplicates.
The database only need to search through one index set (not 3) and might do some optimised stuff in the back because it is looking for 3 keys in the same set (instead of 3 key in 3 index sets) - it's my gut feeling, not sure if this is exactly correct...
You can make one amendment in the 2nd design you have proposed by keeping the user type column as well, which describes whether the user is any of author, illustrator and editor. the id will vary from 0 - 7, you can store the decimal value of the bitwise data. as if a person is Editor & Author then,
1(Editor) 0(Illustrator) 1(Author) => 5
So when you will perform any select/search on that table you can add filters where user type in query.
Do you need to validate, for example, that the author is defined as author in "Author" before you link to a book as author?
Do you care to do a query to know who are all authors/editors/illustrators defined in your database?
You have created N-N link between the entities, however, you have the "auhorId", "editorId" and "illustatorId" in the "Book" entity!
The proper way would be to have the resolution of the many-to-many relationship by having another table, and end up with something like this
BOOK, has ID, TITLE, DESC, etc.
PARTICIPANT (suggested name for all people), has ID, NAME, BIO, etc
AUTHOR, has BOOK_ID, PARTICIPANT_ID
EDITOR, has BOOK_ID, PARTICIPANT_ID
ILLUSTRATORS, has BOOK_ID, PARTICIPANT_ID
OR, instead of (3, 4, 5), BOOK_PARTICIPANT, has BOOK_ID, PARTICIPANT_ID, PARTICIPATION_TYPE (code for author, editor, illustrator), or even use flags (IS_AUTHOR, IS_EDITOR, IS_PARTICIPANT, where one is required to be set)
If you need to validate the participant as author, editor, illustrator before being able to link to a book, you need to add three flags here to to PARTICIPANT: IS_AUTHOR, IS_EDITOR, IS_ILLUSTRATOR
Hope this helps

designing a database for a city travel guide application which let users explore places and plan trip [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am currently working on a city travel guide application which let users explore places and plan trip.
In the account module, the following functions are to be considered:
User can register by providing primary email and password.
Registered users can add their personal details like they can add full name, secondary email, country and city.
User can setup their profile like they can add profile picture, Display name, places they have visited etc.
When they open own/ other's profile, their profile info (like photo and Display name) and statistics like their 'trip' count, 'likes' count, 'reviews' count are to be shown.
I have designed database tables for account module as follows:
1. User_Account_details(user_id, primary_email, secondary_email, password)
2. User_Personal_details(user_id, first_name, last_name, country, city)
3. User_Profile(user_id, profile_picture, display_name)
4. User_Statistics(user_id, trips_count, likes_count, reviews_count)
There are 3 more tables for cities and countries so that when user add country , then the app retrieve it from database and according cities are displayed in suggestions for city textbox.
1. country(country_id, country_name)
2. city(city_id, city_name)
3. country_city_association(country_id, city_id)
Can anyone tell me if there is anything missing in my tables? or the tables are normalized or not? or if they are missing proper relations etc? I am newbie in database design.
It would be better if the City table included the 'country_id'; this way you won't need the 'country_city_association' table. A city can only be in one country! Whilst it could be claimed that a valid entry in the 'city' table would be 'Boston', which would require at least two entries in the association table (Massachusetts and Lincolnshire), this isn't a very good idea.
The User_Personal_details is completely wrong. If you want to show all the places where a user has visited, then this table only needs user_id, city_id and a date. If the intention was to store where the user is normally located, then the city_id should be in the user_account_details table. First and last names should also be in the account details table.
The user_statistics table would prevent the database from achieving third normal form: all the data in this table can be retrieved by querying the other tables.

Database design: 3 types of users, separate or one table? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I have 3 types of users:
Admins
Suppliers
Employees
Each user type will have different user interface and access different types of data. Their only similarity is they are using one web application but they access totally different things. Is it better to put them all in one user table like tbl_users or is it better to create tbl_admins, tbl_suppliers, tbl_employees?
What you need to consider when designing tables is not necessarily what they'll have access to and how that is similar/dissimilar, but rather how the user levels themselves are similar/dissimilar.
For example, if the user types will have the same attributes (name, email, birthdate, etc), then they belong in one table together with a column indicating their privilege level.
This also facilitates changing privilege levels for a user, whereby you can make an ordinary Employee into an Admin, for example, by just updating the record in the user table.
If Suppliers are a different type of object with different attributes than the other two, Suppliers may belong in their own table.
Or, one more thing to consider: You might use a users table that holds only very limited information about users of all three types, and if the types have extended attributes that don't relate well to one another, you can store those in other tables with a foreign key back to the main users table.
There is also a third choice: put the columns that all users have in common into tbl_users, and create three tables for tbl_admins, tbl_suppliers and tbl_employees joining to tbl_users as 1 to 0..1. You should consider this choice as an alternative when the number of shared columns is significant.
It depends on how similar their data structures are. If they are similar, then perhaps you could put them all in one table. But, if they have a lot of different fields and you'll end-up with lots of NULL values...and then it's better that they're all in separate tables.
Best to keep all your login info in one place. If you were ever to make a change to your login process, having 3 different tables would mean having to change the code in 3 separate places.
If a user can belong to more than one role, consider making a UserRoles table. Otherwise, adding an additional field to the existing table - such as RoleType - would help differentiate the different types of users.
You should just include them in one table and create a field/attribute that would be an indicator of whether the user is an Admin, Supplier or Employee.
It's simpler if you centralize it that way.
The concern on how/what they access would be under the software you develop. You can either fetch/constrict the UI[or whatever they access in the software system] basing from the type of user you have.
I usually just hide and show stuff according to the type of user I have
Hope this helps..

How to Write a Query to Merge Two Accounts and their Activity Logs into One? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 14 years ago.
Improve this question
We frequently have users that create multiple accounts and then end up storing the same lesson activity data more than once. Once they realize the error, then they contact us to merge the accounts into a single one that they can use.
I've been beating myself to death trying to figure out how to write a query in MySQL that will merge their activity logs into a single profile so that I can then delete the other profiles, but I still can't find the query that will work.
The tables look like this:
CREATE TABLE user_rtab (
user_id int PRIMARY KEY,
username varchar,
last_name varchar,
first_name varchar
);
CREATE TABLE lessonstatus_rtab (
lesson_id int,
user_id int,
accessdate timestamp,
score double,
);
What happens is that a user ends up taking the same lessons and also different lessons under two or more accounts and then they want to take all of their lesson statuses and have them assigned under one user account.
Can anyone provide a query that would accomplish this based on the lastname and firstname fields from the user table to determine all user accounts and then use only the user or username field to migrate all necessary statuses to the one single account?
Attempting to merge this data via last/first is a horrible idea, the more users you have, the more likely you are to mesh up incorrect entries. You have IDs on your tables for a reason, use them.
I don't see any reason why you can't say "I want to merge user 7 into 12" and then do the following:
UPDATE lessonstatus_rtab SET user_id=12 WHERE user_id=7;
DELETE FROM user_rtab WHERE user_id=7;
One of my current clients is facing a similar problem, except that they have dozens of tables that have to be merged. This is one reason to use a real life primary key (natural key). Your best bet is to try to avoid this problem before it even happens.
Another thing to keep in mind, is that two people can share both the same first and last name. Maybe you don't consider this an issue because of your user base, but if they're already creating multiple accounts how long is it until they start making up fake names or creating names that are almost the same, but not quite. Names are generally not a great thing to match on to determine if two people are the same or not.
As to the technical part of your question, it depends a lot on what the business rules are. If they have the same lesson in there twice with different scores do you use the highest score? How do you decide to which user account to link everything? No matter what, it's going to probably be a multi-step process.
How about this, assuming we are merging user_id 2 into 1.
This updates the lessons done under 2 that have not been done under 1.
UPDATE lessonstatus_rtab
SET user_id = 1
WHERE user_id = 2
AND NOT EXISTS
(SELECT *
FROM lessonstatus_rtab e
WHERE e.lesson_id = lessonstatus_rtab.lesson_id
AND user_id = 1)
Anything leftover is a duplicate and can now be removed:
DELETE FROM lessonstatus_rtab
WHERE user_id = 2