SQL Database Structure for Users + Memberships + Groups - mysql

I'm developing an e-commerce site and I wanted to get this community's thoughts on a database structure for groups, users, and their memberships.
THE GOAL: Determine a user's group membership(s) and access privilege at login. A user could be a seller on this site, an admin, a site support, or ANYTHING. Must be scalable.
INITIAL THOUGHT: Three separate tables: users, groups, and memberships. At a successful login, search the membership table for the user's ID and get group ID's from that same row in the membership table. From there, another query to get group information from the groups table (like name of group, description, etc). Store the memberships in the user's session and call it a day.
THE CONCERN: At log in, I don't want to unnecessarily perform additional queries. The above "initial thought" consists of 3 separate queries at login.
THE QUESTIONS:
Is this the right approach?
Any better design solution(s)?
Better to break admins into their own table, or toss 'em into the same groups table?

The database design is reasonable. As a user can belong to multiple groups and can have multiple memberships, two additional tables USER_GROUP and USER_MEMBERSHIPto hold the relations between users and groups and between users and memberships will be necessary.

Related

Which is more efficient: Multiple Mysql tables Per User or a Combined Table per category

I've been thinking a lot about Database Management and I am trying to figure out the best possible Way to Organize (Users, Products, orders, Customers, Etc).
Every User will have their own Products that the user will add into the database.
For Database Management all The users will be stored on the same table. Now my question is should all the Products be stored on the same table with a user ID assigning the products to the correct user or should the Products be stored on an individual table That is created when a user is created?
Note: Each user can Have more than 100k products.
And also how would your answer effect product synchronization?
I'm thinking about a MySQL to SQLite and vice versa for offline use.

best practice for designing system with multiple user type

We have a system with two main roles: service provider and customer. The provider side is users like doctors, nurses, and caregivers. The customer side is just the customer. all user types contain some common data and some uncommon data. in the current system, we have a table for each user type, and for common data, we have User table. currect system ERD is:
https://s4.uupload.ir/files/screenshot-20210710165449-1007x662_tpwd.png
in the current system, we have a lot of tables and we think about reducing them. our vision is to bring all user types in a single table called User and instead of a lot of tables, we have more columns. of course in some users, we have empty cells that do not belong to this user type.
I have 4 questions:
is it ok to bring customers and providers to a table like User?
what is the optimal number of columns in a table?
load a row with a lot of columns OR relation between different tables?
provider type should be a separate table or can be an enum?
It is best to put all users in single table. So when you check login there is less place to do mistake. When selecting user you dont need to use SELECT * FROM... You can use SELECT id, username, name FROM...
Dont put too many columns, if there is some data which you dont need when searching or displaying users, you can create helper table "user_meta" with dolumns user_id, meta_key, value where user_id and meta_key are primary key
Answered by first 2 answers
Provider type should be enum if there will not bee needs to expand with additional types.

Do I need more than my current 3 tables in order to create the relationships explained in my post?

I'm trying to create a clone of a very popular application called Discord which allows people to communicate over voice, video, and text.
Discord allows every user to create their own servers and invite people to them. In order to allow users to create servers, I first created 2 tables - users and servers
Users table:
id, username, password
And
Servers table:
id, name, image, userId
So the relationship between these 2 tables is that a user can create and have many servers and a server belongs to a user. So far, so good.
Once a server is created, users can join the server as members of that server. A user can join as many servers as he wants and a server can have many members. I achieved this by creating a server_users junction table and a many-to-many relationship between users and servers:
Server_Users table:
id, userId, serverId
This works fine, however, I'm not sure if the logic behind the many-to-many relationship between users and servers is sound. To me it seems like I'm applying 2 relationships between users and servers and I don't know if this is correct. Maybe I need more tables to make the relationships clear?
User has many servers and a server belongs to a user ( Because a user is the owner/creator of a server, and the server belongs to only 1 user - his creator )
Server has many users and users have many servers ( As in every server can have many members and every member can be a part of many servers )
I think it's good design, almost a textbook example. The goal is that the tables are in normal form, which is the case here.
An alternate design also with three tables, if you would like to "merge" the two relationships, is to also use Server_Users to store the user who owns the server, marked as such with a boolean column. However, I think it is more efficient how you did it with a foreign key (userId), as you will only need one join for the 1-to-N relationship.
I would also add that the design of the table is not only motivated by getting this right "theoretically", but also by your use case. Picking a design depends on the kinds of queries that you will run against the database. If you list all users on a server including the owner, but never the owner alone, then the alternate approach may be faster.
Another aspect is integrity constraints: do you require that the owner of the server is also a member of that server, or is it fully independent? This also influences the design.
An alternative in the context of large quantities of data that do not get updated often, is to denormalize everything, by nesting the users (replicated) inside the server tuples.
I think your approaches are good.
As discribed before it's depending on your use cases or future functions.
In my opinion you have this possibilities:
Possibility 1
user
id
username
password
server
id
name
image
userId
adminId (references user id of admin/owner/creator)
user_server
id
userId
serverId
Possibility 2
user
id
username
password
server
id
name
image
userId
user_server
id
userId
serverId
admin (null if not an admin and true if an admin/owner/creator)
Possibility 3
user
id
username
password
server
id
name
image
userId
roleId (1=normal user, 2=admin,3=moderator)
user_server
id
userId
serverId
role
id
rolename
With possibility 1 you are limited to one owner of a server.
With possibility 2 you could add a "admin flag" to each user wich is allowed to manage the server. (like in chat groups of a messanger where exists multiple group admins)
With possibility 3 you could add a system to manage the rights of the corresponding users.

sql - normalize user table with it groups but both can login

Hi currently i have 3 tables:
users
|id|name|email|password|last_login|created_at|
user_groups
|user_id|group_id
groups
|group_id|name|email|password|last_login|created_at|
Group can login so it when i can view statistics for specific all it users, that's why i put email and password too.
the problem is users and groups got almost everything same. 1 group can contain many users.
Is there anyway to make this more normalize and user still have their specific groups?
I would just use the user authentication to detect whether the user belongs to any group or not. That way you don't need all these extra fields for the group.
If you only want one specific user to be able to look at the group statistics you could add an admin_id to the user_groups table (which would relate to a user id)

MySQL Tables Arrangement

I have a corporate website which is used to communicate between staff members as well as staff members with clients. There are internal users who can login and work with their mail using web interface, there is a list of external clients with email address and phone numbers which internal users can use to write an email or make a call. Sometimes clients become staff members, sometime staff members gets fired but stays in the database as they can become future clients.
There are two MySQL tables for those two types. First one is a full list of all people, and there is a separate table of internal users partially duplicating the first table. The second table for the people who can login so it has login, password and some permisisons fields but it also have last name, first name, job, address etc. which is already in the first table.
So all internal users have two entries - one entry at the users table and one at people table. People table has internal users and all the external clients data.
I'm thinking to make one table from those two just by adding internal users fields to the people table such as login, password, permissions etc. so whoever have those fields filled considered to be internal users. That would probably simplify my SQL queries and get rid of edless SQL JOIN constructions as I constantly have to fetch data from both of the tables in order to get full data on a user.
Basically I want users table to become part of the people table. Is there any negative consequences per your experience may be in terms of security or conviniency that can be a problem for such an integration of clients and users being put together in one table?
I don't think you should get rid of the users table. The distinction between internal and external users is too important to depend just on the use of columns.
Instead, make users a "subtype" of people. So keep the people table and include all the users in them, with the appropriate "people" fields. Then in your users table, include the internal information along with a people id.
With this structure, it is easy to get "everyone" (from people) and "internal users" (from users). To get external users, you need to do something like:
select p.*
from people p
where not exists (select 1 from users u where p.personid = u.personid);
This should be a fast operation, with a index on personid. You could maintain a flag in the people table, indicating whether someone is or is not a person, but you would need a trigger to keep it up-to-date. Probably not worth the effort.