Database structure and query building - database

Please advise how to accomplish this task.
There is an entity - the user.
He can create a group in which there will be other users with certain rights.
Here I'm interested in how to correctly cost requests to get groups for the user and guest.
I assume that the group will have corresponding fields for which I will make a selection, but I don’t really understand how to properly store the role of the guest in this group. I have one idea, but I'm not sure if it's ok.
interface Group {
id: string;
ownerId: string;
guestsId: string[];
// or my idea :)
guests: Array<{
guestId: string;
role: string;
}>
}
Perhaps you need to create another table for this? I am using relational db
Same way. Question number 2.
Each user has a photo, and each group has pictures.
I need to restrict access to pictures (getting will be through api with middleware, not static) for different users.
Pictures in a group can only be viewed by its members.
A user's photo can be seen if you are in the same group with him.
I don't have many ideas here. I see the problem that in order to get a picture, you need to check which groups the user who requested the picture belongs to.
All that came to mind is when generating a jwt token, get a list of user groups and add them to this token.
But I'm not sure.
I would appreciate your ideas and advice.

From a database standpoint, I see tables:
User table
Userid (PK)
UserName
UserPhoto
Group table
Groupid (PK)
GroupName
Rights table
Rightid (PK)
RightName
Picture
Pictureid (PK)
PictureLocation
Link tables
Group_has_rights
Groupid (FK)
Rightid (FK)
Group_has_users
Groupid (FK)
Userid (FK)
Groups_has_Pictures
Groupid (FK)
Pictureid (FK)
Using the Groups_has_SOMETHING tables, you establish many-to-many relations. This way, users, rights and pictures can be associated to many groups.
It gives you complete flexibility for match current and future requirements and combinations.
With link tables, this being a relational database, you can use JOIN statements to extract any list of required items. No need to iterate through lists in your code, the database does it all.
For your guest users, I do not understand your requirement. Define what rights a guest user should have and associate it to a group that has those rights in Groups_has_Rights.
Your application code can associate a guest1, guest2, ... user that is created on the spot, with a link to the appropriate group(s).
For your pictures, you get the list of groups for the current user in Groups_has_User. Then you get a list of pictures to display through Groups_has_Pictures, for the groups you listed above. Use JOIN in your SQL.
For the photos, you get the list of groups for the current user in Groups_has_User. From that list, you get a list of all other users that are in the same groups, again from Groups_has_User. Then from the users list, you select the UserPhoto. Again, use JOIN in your SQL.
Obviously this only shows the basic structure of tables and relations. Each table will contain more information, I just demonstrated the squeleton.

Related

Database schema for profile and order

I am working on a bank application in which a customer can open multiple accounts for different product types like: Insurance, Investment and annuity etc.
Each customer has a profile and we are saving that information in 12 different tables such as : Personal,Contact,Address,Affiliation,Financial,Investment,Asset,Liability,NetWorth and so on.
Now to open each account we have to collect and save same kind of information like for customer profile but we cannot overwrite the customer profile with that as we have to keep track of each accounts information when its submitted to the point when it get opened.
So in terms of solution we think either to have replica of these 12 tables for each account or to save the JSON for each table in one table only which has 12 columns for each of above table and populate UI with that.
Can somebody if have prior experience suggest us how to do this in best way.
I would determine which information will not change between accounts. For example, name, birthday, ssn, etc. These constant fields can form a table called customers. If there are no constant fields, then you can use a placeholder id, which simply helps to associate accounts to the same user.
I would also create a table for Accounts and use the account_id as a foreign key for all your customer information that may change between accounts. Each row in the Accounts table will be owned by a customer from before.
So the relationship between customers and accounts would be one to many, and the relationship between accounts and "account specific customer info" would be one to one.

Database Design Advice for a Social Network App Needed

I am very new into backend stuffs like databases. That being said, I lack the database design knowledge.
I am wondering how and what is the best design for my scenario.
I am creating a social network app where the users can create groups and join other groups. Those groups have places in it. Those places are created by the User in the group
User
Group
Place
Rules:
One User can create and join many Groups
One Group can contain many Users
One Group can have many Places
Each Group have an admin User
I currently have 3 separate tables
1. USER TABLE
ID, EMAIL, USERNAME, PASSWORD, PROFILE PICTURE
2. GROUP TABLE
ID, NAME
3. PLACE TABLE
ID, NAME, COORDINATE, RADIUS
I am extremely confused in designing the proper database for it it.
Question:
How should I design the relation of the table.
I would like to have one User (maybe more) in a Group that has the permission to do certain stuff that normal User cant do. Such as Creating New Place, Deleting A Place
How should I define my table structure?
Any thoughts please? Any help is greatly appreciated!!
Thank you
You will need to have one more table in order to create what is known as a many to many relationship between the users and the groups.
Since you didn't specify the rdbms you are working with, I'll use SQL Server for my code:
CREATE TABLE TblUserToGroup
(
UserToGroup_UserId int FOREIGN KEY REFERENCES TblUser(UserId),
UserToGroup_GroupId int FOREIGN KEY REFERENCES TblGroup(GroupId),
UserToGroup_IsAdmin bit DEFAULT 0
CONSTRAINT UC_UserToGroup UNIQUE(UserToGroup_UserId, UserToGroup_GroupId)
)
As you can see, there is also an IsAdmin column that can take values of 0 or 1. If you only want one admin user for each team, you can add a check constraint to prevent having more then one admin for each group.

Users, Customers, Tenants, Employees - All in the same table?

In this case let me be more specific about the problem
I've got a peoples table(with customer & supplier) and I've got a users table(for users who can login).
Currently I have this DB structure
Customers -> Organisations -> linked through rel_customer_addresses to address table.
(as 1 customer could have delivery_address, invoice address etc.)
Users -> Tenants -> linked through rel_users_addresses to the address table
(as 1 user could have delivery_address, invoice address etc.)
Now I've got in the invoice table customer_key. The problem is when the user himself is the customer and the invoice is from one of his customers. How do I indicate my web app to look up user and not the customer?
Since you're looking at 2 separate entities (customers and users), I would go ahead and use 2 separate tables and have them share a unique identifier (i.e., username, SID).
That way there's no chance of one seeing information from the other without the appropriate permissions.
There are several ways to control this, but the logic is something like this.
If userID exists in table user, do this.
If userID exists in table customer, do this.
If userID exists in table user AND table customer, do this.
That way you can control the situation completely either independently or together. In other words, you could grant special permissions to userID that is found in table customer, or just make it completely separate (similar to say, how facebook makes a separate 'identity' for pages vs the account it's registered to).
Hope that helps!

Which is the best way to relate some tables?

I want to make an application where there will be different users and each user will have a set of friends which will be put in categories. There will be some default categories, but the user will be able to add his own. I was wondering which will be the best way to do this.
My idea is to have 3 tables - user, friends and categories.
The user table to have fields (one to many) for friends and categories (but I don't know if the user table will need any information about the friends and the categories at all).
The friends table to have a field for categories (one to many) and a field for the user (many to one).
The category table to have fields for user (many to many?) and friends (many to many?).
I'm not sure about the relations, too. I'm using PHP with MySQL and Symfony2 and Doctrine2. Please help!
EDIT
Maybe I haven't described exactly what I need. When you open the app, you see a login form. If you don't have an account, you should register - the registration creates a new user. This user isn't connected with other users (I'm still new to programming and I want something a little easier so it's something like phonebook). Each user has a list of friends and a firend is a row in a table with fields such as name, addres, phone, email, photo, birthday and so on, but they are added by the current user. The friends are not users. Every user is in fact an account with password and username and when you log in there is just a list of friends. So each user creates categories for himself and he has nothing to do with other users and their categories. The category will have only id and name.
So the idea is that you create an account, then create some categories and add friends to them just to have an organiser when you friends are born or where they live, or which is their phone number, but you create them and add the information about them, they are to users themselves. It's not like a social network. Just a notebook where each user can write info about his friends.
First of all, you need to understand the role of intersection tables: if user A labels user B as a friend (i.e. there is a many-to-many relation from user to itself), and you create a new table to represent that relation (the friends table), any additional information about this "friendship" should be linked to that table. So, if a user categorizes his friends in some way, the category applies to friends, not to user. There's no need for a relation between category and user for this specific purpose.
Update: since friends are not users, the friends table will not be an intersection table (and thus have only one reference back to user, denoting the "owner"), but the rest of the answer still applies.
I'm assuming each category will be a row in the category table. Additional information about the category might be added, but it should be limited to that. For instance, if you want to know which user created a category, you could add a foreign key to user labeled for instance "owner" or "created_by". That might be useful if categories created by one user are not to be seen by others.
Finally, you can relate friends with category. If User A can put user B in at most one category, then a foreign key from friends to category should suffice (i.e. a one to many relation). Otherwise, you might need another many-to-many relation, so an additional intersection table should be created (for instance friend_category).
You could avoid this extra table by employing denormalization, having multiple rows in friends where both users are the same (and in the same order) but the category is different (see also this example). Whether this is advantageous or not is beyond the scope of this answer, but IMHO using an extra table is better for now (it might seem more complicated, but it will be easier to maintain in the long run). (Update: if friends is not an intersection table, denormalizing like this is not really an option, so stick with the friend_category table)
In the end, your layout would look like this:
user friends friend_category category
---- ------- --------------- --------
(user fields) <-- user (owner) <-- friend (category fields)
(friend fields) category --> user (owner) --+
^ |
| |
+--------------------------------------------------------------------+
I can suggest the following table set for this (this scheme applies to the phonebook or social network tasks as well):
Table "Users" that stores all the information about users:
UserId
Name
Phone
Address
... (any other fields)
Table "Categories" that stores information about relationship categories:
CategoryId
Name
Table "Relationships" that stores information about relationships between users:
FirstUserId -> Link to Users table
SecondUserId -> Link to Users table
CategoryId -> Link to Categories table
So, any user is able to add new categories, and then reference them when adding new relationship to another person.
If you need to select all user's friends, you will have to:
select fr.* from Relationships r join Users fr on r.SecondUserId = fr.UserId where r.FirstUserId = <Current user id>

How to model this one-to-one relation?

I have several entities which respresent different types of users who need to be able to log in to a particular system. Additionally, they have different types of information associated with them.
For example: a "general user", which has an e-mail address and "admin user", which has a workstation number (note that this a hypothetical case). Both entities also share common properties like first name, surname, address and telephone number. Finally, they naturally need to have a (unique) user name and a password to log in.
In the application, the user just has to fill in his user name and password, and the functionality of the application changes slightly according to the type of the user. You can imagine that the username needs to be unique for this work.
How should I model this effectively?
I can't just create two tables, because then I can't force a unique constaint on the user name.
I also can't put them all in just one table, because they have different types of specific information associated to them.
I think I might need 3 seperate tables, one for "users" (with user name and password), one for the "general users" and another one for the "admin users", but how would the relations between these work? Or is there another solution?
(By the way, the target DBMS is MySQL, so I don't think generalization is supported in the database system itself).
Your 3 tables approach seems Ok.
In users table have only ID, username, password,usertype.
In general users table have ID, UserID (from users table), other fields.
Same thing for admin users.
Usertype field will tell you from what table to search for additional info
if(usertype==admin)
select * from admins where userid=:id;
else
select * from general where userid=:id;
Two tables. USERS with user names, first, last, etc. ROLES with roles, and a link back to the user name (or user id or whatever). Put a unique constraint on the user name. Put workstation nbr, email, phone, whatever else you need, in the user table. Put 2 columns in the ROLES table -- USERID and ROLE.
You should decide how much specific information is being stored (or likely to be stored in the future) and make the decision based on that. If there are only a handful of fields for each user type then using a single table is alright.
USERS table (name, type, email, password, genfield1, genfield2, adminfield1, adminfield2)
Make sure to include the type (don't assume because some of the fields particular to that user are filled in that the user is of that type) field. Any queries will just need to include the "AND usertype = " clause.
If there are many fields or rules associated with each type then your idea of three tables is the best.
USERS table (ID, type, name, password)
GENUSERS (ID, genfield1, genfield2)
ADMINUSERS(ID, adminfield1, adminfield2)
The constraints between IDs on the table are all you need (and the main USERS table keeps the IDs unique). Works very well in most situations but reports that include both types of users with their specific fields have to be done in two parts (unioned SQL or subqueries or multiple left joins).
You can solve it with one 'general' users table containing the information thats available for all users and 1 table for every specific user type. In your example you will then need 3 tables.
Users: This table holds only information shared between all usertypes, ie. UserId, Name, Address, etc.
GeneralUsers: This table 'extends' the Users table by providing a foreing key UserId that references the Users table. In addition, information specific to general users are held here, fx. EmailAddress, etc.
AdminUsers: As with GeneralUsers, this table also 'extends' the Users table by providing a foreign key UserId referencing the Users table. In addition information specific to admin users are held here, fx. WorkstationId, etc.
With this approach you can add additional 'specializations' if the need arises by simply adding new tables that 'extends' the Users table using a foreign key reference. You can also create several levels of specialization. If for example admin users are general users as well as admin users then AdminUsers could 'extend' GeneralUsers instead of Users simply by using a foreing key to GeneralUsers instead of Users.
When you need to retreive data from this model you need to which type of user to query. If for example you need to query a GeneralUser you will need something similar to:
SELECT * FROM GeneralUsers
LEFT JOIN Users ON GeneralUsers.UserId = Users.UserId
Or if querying an admin user
SELECT * FROM AdminUsers
LEFT JOIN Users ON AdminUsers.UserId = Users.UserId
If you have additional levels of specialization, for example by having admin users also being general users you just join your way back.
SELECT * FROM AdminUsers
LEFT JOIN GeneralUsers ON AdminUsers.UserId = GeneralUsers.UserId
LEFT JOIN Users ON GeneralUsers.UsersId = Users.UserId
I most definitely would not do a model where you have separate tables as in GeneralUser, AdminUser and ReadOnlyUser.
In database design, a good rule of thumb is "Down beats across". Instead of multiple tables (one for each type), I would create a SystemUsers table, and a Roles table and define a join table to put SystemUsers in Roles. Also, I would define individual roles.
This way, a user can be added to and removed from multiple roles.
A role can have multiple permissions, which can be modified at any time.
Joins to other places do not need a GeneralUserId, AdminUserId and ReadOnlyUserId column - just a SystemUserId column.
This is very similar to the ASP.Net role based security model.
alt text http://img52.imageshack.us/img52/2861/rolebasedsecurity.jpg

Resources