Database modeling - mysql

My question is about modeling a particular situation:
In my model I have tables: User, Offices and Partners.
The system has different user profiles: users of Office (counselors, principals, assistants), users for Partners (Institutions,..), admin users.
What is the best way to model the relationship between office users and partner users if:
- The users are unique (two users should have the same login - should be in only 1 table)
- An office user is associated to only one office
- A partner user is associated only with a partner.
It should be a table for office users and one for partners users?
A many to many relationships in this case would not work, right?
Thanks for your help.

You have not provided enough definition re Partners and Offices, so those parts of the model are not yet complete, but I think the main question you are asking is answered in this ▶Data Model◀. As I understand it:
User (login, UserName is unique, and you do not want that to be unclear)
Users are exclusively (that is the X in the half-circle) Office/Partner/Administrator
that requires a Supertype-Subtype structure. The cardinality is 1::0-1
Users belong to (?) an Office or a Partner, exclusively.
That may be OfficeType or OfficeTitle.
If you define that last item a bit more, I can finish the model.
Readers who are unfamiliar with the Standard for Modelling Relational Databases may find the ▶IDEF1X Notation◀ helpful.

Assuming this model will never change I would add a field to the users to determine where they belong. You could put an enum named user_type with possible values of 'office', 'partner', or 'admin'.. And then you could put in columns of office_id, and partner_id so you could join the tables as needed.

I think the best route would be to go with an account group structure, where you use an association table to determine who's in what group...
group
id | name
group_assoc
group_id | account_id

Related

Database design for tracking and sharing expenses

I want to design a web application for keeping track of the finance of the members of an organization. Certain functions are very similar to Splittr. I define my requirements using the MWE database diagrams:
"Finance" tables: Each user will have one personal finance account, for which I am using the following three red tables:
"SharedExpense" tables: Each user can have shared expenses with other users in many 'shared-expense-groups'. For each group, I am using the following three blue tables:
(Note how each user can define amount of their share, and own category of the shared expense. UserShare table uses a composite primary key.)
The problem: I have to relate the users to their 3 personal "Finance" tables and the 3N "SharedExpense" tables (where N is the number of 'shared-expense-groups' the user belongs to).
Attempted Solutions:
Multiple databases. Each user has a unique database for their "Finance" tables. Each 'shared-expense-group' has a unique database on the server. I can then relate the users from one master database with the following four purple tables:
Drawbacks: Foreign keys come from different databases, large number of databases to be backed up.
Multiple tables. I can create all the tables in the same database and relate all of them with the four green master tables:
Here, the number of tables is a potential problem. If there are M users and N 'shared-expense-groups, then there will be 3M + 3N tables!
The question: Is there more elegant and simpler database design for the purpose? If not, which of the above two solutions is better and why?
Links to relevant, previous StackOverflow Q&A:
Personal finance app database design
Database design for tracking progress over time
SQL for a Household Bill splitting db
Comparing 1 Database with Many Tables to Multiple Databases with Fewer Tables in Each
There is to much to describe all the challenges in a summary, but I'll pick out a few.
Fundamental design violations: such as a table/database for each user
entity design, 3NF: such as category.budget and ledger.transaction_type
referential integrity/relationship design:
account is for one user, but account table does not contain the user id;
usershare is a subset of ledger, but they both point to a user;
object naming concerns:
clear and consistent naming entities, based on real usage. Is a member a user or a user a member? If they are the same, choose one name. If they are not the same, the design is different. Do staff use client or customer rather than member?
consistency in your key naming. The key name should directly tie it to the source entity. Members.ID should be referenced as members_id, rather than user_id. However, see the next entry before correcting this.
be consistent in your entity plurality. The general consensus is that the name should describe a single record (User) rather than all the records (Users).
ledger.spent_on - that name is not obviously a date. It could be pointing to a user or category as well. An attribute name should describe the attribute without needing additional explanation. For example, ledger.Purchase_Date is self explanatory. It should also be clear how it relates to the entity. UserShare.Share doesn't really tell me what it contains.
Sorry to be blunt, but I would start over. Consider what you have as a good trial run and start again using the additional information you have.
Ask questions of your designs (Are all users members? Are all members users?). If the answer is anything other than Yes or No, break it down further.
Try what-if scenarios (What if a shared ledger exceeds the category budget? How will previous spending be perceived if the category budget changes?)
Consider what reporting questions may be asked (Who went over budget? How much are we spending on this category?) and then consider the query to answer the question.
Read up on 3NF and maybe some of the higher normalization levels as well. Whereas 3NF is pretty nearly the minimum normalization, the higher levels become increasingly specialized and may or may not be appropriate for you design.
The better you understand your data AND business, the better your design will be, and the better your end product will turn out.

Proper way to model user groups

So I have this application that I'm drawing up and I start to think about my users. Well, My initial thought was to create a table for each group type. I've been thinking this over though and I'm not sure that this is the best way.
Example:
// Users
Users [id, name, email, age, etc]
// User Groups
Player [id, years playing, etc]
Ref [id, certified, etc]
Manufacturer Rep [id, years employed, etc]
So everyone would be making an account, but each user would have a different group. They can also be in multiple different groups. Each group has it's own list of different columns. So what is the best way to do this? Lets say I have 5 groups. Do I need 8 tables + a relational table connecting each one to the user table?
I just want to be sure that this is the best way to organize it before I build it.
Edit:
A player would have columns regarding the gear that they use to play, the teams they've played with, events they've gone to.
A ref would have info regarding the certifications they have and the events they've reffed.
Manufacturer reps would have info regarding their position within the company they rep.
A parent would have information regarding how long they've been involved with the sport, perhaps relations with the users they are parent of.
Just as an example.
Edit 2:
**Player Table
id
user id
started date
stopped date
rank
**Ref Table
id
user id
started date
stopped date
is certified
certified by
verified
**Photographer / Videographer / News Reporter Table
id
user id
started date
stopped date
worked under name
website / channel link
about
verified
**Tournament / Big Game Rep Table
id
user id
started date
stopped date
position
tourney id
verified
**Store / Field / Manufacturer Rep Table
id
user id
started date
stopped date
position
store / field / man. id
verified
This is what I planned out so far. I'm still new to this so I could be doing it completely wrong. And it's only five groups. It was more until I condensed it some.
Although I find it weird having so many entities which are different from each other, but I will ignore this and get to the question.
It depends on the group criteria you need, in the case you described where each group has its own columns and information I guess your design is a good one, especially if you need the information in a readable form in the database. If you need all groups in a single table you will have to save the group relevant information in a kind of object, either a blob, XML string or any other form, but then you will lose the ability to filter on these criteria using the database.
In a relational Database I would do it using the design you described.
The design of your tables greatly depends on the requirements of your software.
E.g. your description of users led me in a wrong direction, I was at first thinking about a "normal" user of a software. Basically name, login-information and stuff like that. This I would never split over different tables as it really makes tasks like login, session handling, ... really complicated.
Another point which surprised me, was that you want to store the equipment in columns of those user's tables. Usually the relationship between a person and his equipment is not 1 to 1 and in most cases the amount of different equipment varies. Thus you usually have a relationship between users and their equipment (1:n). Thus you would design an equipment table and there refer to the owner's user id.
But after you have an idea of which data you have in your application and which relationships exist between your data, the design of the tables and so on is rather straitforward.
The good news is, that your data model and database design will develop over time. Try to start with a basic model, covering the majority of your use cases. Then slowly add more use cases / aspects.
As long as you are in the stage of planning and early implementation phasis, it is rather easy to change your database design.

MySQL database design - trouble figuring out table relationships

I'm trying to figure out the best way to design these tables for a website I'm making for a school club. I want to set it up so each user can have multiple emails, phone numbers, and addresses tied to their account. To do this I tried to tie all these things to a contacts table and store the contacts id in the users table as a foreign key. The contacts id is also a foreign key in the emails, phone numbers, and addresses table. Is this a feasible way of relating these tables or should I just cut out the middle man (contacts table) and store the user id in the emails, phone numbers, and addresses tables?
Just in case my description of the relationships weren't enough, here is an ERD for the tables:
Sorry for such a "noob" question, it's been a while since I had to build a database with more complexity than 2 tables. Any general tips for database design are very much welcomed as well.
All you need to do is remove the Contacts table and store the user_id in the tables on the right, rather than contact_id.
Remove contact_id from Users as well.
I have dealt with this very question in the past. We did it wrong and we were sorry.
The determining factors should be these:
Will you have any other category of person that isn't a user, for whom you need to store contact information?
Will those kinds of persons somehow be "fungible" with users?
If you answer both these questions "yes," keep your contact table. Otherwise get rid of it.
The mistake made by a team I worked on was our answer to the second question. We had medical patients and doctors/nurses/etc as our categories of people. We stored their contact information together. But we shouldn't have done that because patients' contact information is very sensitive and confidential, but health care provider information is much less so. We were always wishing we didn't have the two kinds of data in just one set of tables after the system became successful.
Unless you can convince yourself you need your contact table, get rid of it, I say!
Yes I would cut out the midle man:
Although I was tempted to go the 'contact_type' route, I have found that there are usually validations and different data types which become more complicated when the contact is generic. For instance a table that has address fields is not the same as a phone number and having both presents more complexity and less readability.
This model focuses on simplicity, e.g. a user has many emails and an email belongs ot a user.
According to me you can design DB accordingly
Table 1 : Users
UserID //PK
Name
Table 2 : Contacts
ContactID //PK
UserID //FK to Users
ContactTypeID // FK to ContactType
Value
Table 3 : ContactType
ContactTypeID //PK
ContactTypeName
Description
Table 1 is pretty clear stores user information
Table 3 holds information about contacttype i.e email, home phone, mobile, home address, shipping address, etc
Table 2 holds information about user, contact type and its value
like cinatacttypeid corresponds to mobile than value is , etc.

Object Model Design

I had a question about the best way to handle this type of data.
In my system, I will have many users and many accounts... users are able to belong to many accounts, and accounts will have many users. I'm guessing the best way to accomplish this is with three tables
users
accounts
& users_accounts
my question is, when someone signs up for a paid account... where should I store the flag that distinguishes between regular users of an account and account holders? Should there be an owner flag in the users_accounts table?
Can I assume that one account cannot have more than one user (1-to-many relation)? In that case, two tables would be sufficient:
users
accounts
Where accounts contain a reference to a user id. A separate relationship table would be superfluous when there is no many-to-many relation.
Then the question arises: can a user have both paid and unpaid accounts? If so, the flag belongs in accounts. Otherwise, it belongs in users.
Taking your clarification into account, your three tables design is appropriate. The answer to your question then completely depends on how you want paid accounts to work.
Will a paid user have extra functionality in all accounts? Then the flag belongs in users.
Will any user have extra functionality in a paid account? Then the flag belongs in accounts.
Will a paid user have extra functionality only in paid accounts? Then the flag belongs in users_accounts.
If every account has only one owner, then you should put a user id representing the owner in the accounts table.
Users table will have only the user related data... name, surname, etc...
accounts will have the info of the account... type and any other data...
The key is that users_accounts is a relation table between Usersand accounts so it will have any linking data from the Users to the accounts and THERE you should put the flag because is there when you set the relations.
Add a paid flag to user_account.
Example Attributes:
user (id, name, street ...)
account (id, name ...)
user_account (user_id, account_id, paid)
You can tell by the paid column if the user is a premium account member or not.

Permissions for web site users

I'm working on a web site where each user can have multiple roles/permissions such as basic logging in, ordering products, administrating other users, and so on. On top of this, there are stores, and each store can have multiple users administrating it. Each store also has it's own set of permissions.
I've confused myself and am not sure how best to represent this in a db. Right now I'm thinking:
users
roles
users_roles
stores
stores_users
But, should I also have stores_roles and stores_users_roles tables to keep track of separate permissions for the stores or should I keep the roles limited to a single 'roles' table?
I originally thought of having only a single roles table, but then what about users who have roles in multiple stores? I.e., if a user is given a role of let's say 'store product updating' there would need to be some method of determining which store this is referring to. A stores_users_roles table could fix this by having a store_id field, thus a user could have 'store product updating' and 'store product deletion' for store #42 and only 'store product updating' for store #84.
I hope I'm making sense here.
Edit
Thanks for the info everyone. Apparently I have some thinking to do. This is simply a fun project I'm working on, but RBAC has always been something that I wanted to understand better.
This is probably obvious to you by now, but role based access control is hard. My suggestion is, don't try to write your own unless you want that one part to take up all the time you were hoping to spend on the 'cool stuff'.
There are plenty of flexible, thoroughly-tested authorization libraries out there implementing RBAC (sometimes mislabeled as ACL), and my suggestion would be to find one that suits your needs and use it. Don't reinvent the wheel unless you are a wheel geek.
It seems likely to me that if I have permission to do certain roles in a set of stores, then I would probably have the same permissions in each store. So having a single roles table would probably be sufficient. So "joe" can do "store product updating" and "store product deletion", then have a user_stores table to list which stores he has access to. The assumption is for that entire list, he would have the same permissions in all stores.
If the business rules are such that he could update and delete in one store, but only update, no delete, in another store, well then you'll have to get more complex.
In my experience you'll usually be told that you need a lot of flexibility, then once implemented, no one uses it. And the GUI gets very complex and makes it hard to administer.
If the GUI does get complex, I suggest you look at it from the point of view of the store as well as the point of view of the user. In other words, instead of selecting a user, then selecting what permissions they have, and what stores they can access, it may be simpler to first select a store, then select which users have access to which roles in that store. Depends I guess on how many users and how many stores. In a past project I found it far easier to do it one way than the other.
Your model looks ok to me. The only modification I think you need is as to the granularity of the Role. Right now, your role is just an operation.
But first, you need a store_role table, a joint table resolving the Many-to-many relationship b/w a role and a store. ie, one store can have many roles and one role can be done in many stores.
Eg: StoreA can CREATE, UPDATE, DELETE customer. and DELETE customer can be done in StoreA, StoreB and StoreC.
Next, you can freely associate users to store_role_id in the user_store_roles table.
Now, a user_store_role record will have a user_id and a store_role_id:
A collection of
SELECT * FROM USER_STORE_ROLE WHERE user_id = #userID
returns all permitted operations of the user in all the stores.
For a collection of users's roles in a particular store, do an inner join of the above to user_store table adding a WHERE part of like
where STORE_ROLE.store_id = #storeID
Put a store_id in the user_roles table.
If this is Rails, the user model would have_many :stores, :through => :roles