Relational database design for photography website - mysql

I'm creating a database for a photography website and I want it to allow three main things -
Allow the owner/admin to create client accounts and credentials,
Specifying which photos should go into three different portfolio galleries on the site, and,
Displaying a unique client's photos (and only their photos!) to them when they log in.
This is my first database design ever - based on responses below, I've added that emphasis ;) and edited the design as below.
IMAGESimage_id,filename,description,client_id,date_uploaded,
USERS/CLIENTS
client_id,
client_name
username,
password,
PORTFOLIO
portfolio_id,
portfolio_name,
PORTFOLIO_IMAGES
id,
image_id,
portfolio_id,
Am I correct in thinking that the final id in PORTFOLIO_IMAGES would allow me to display one image in multiple galleries?
Thanks

As it is your first DB-Design and as you may have mentioned in the comments here is something essential missing: ER-Diagram. This helps a lot understanding what's going on.
ER-Diagram
Synonyms: User=Account, Image=Photo, Gallery=Portfolio
Known Roles: "Admin", "Client"
Examples for Rights: "Create Account", "Delete Account", "Watch images", "Add Gallery", "Remove Gallery", "Upload image", "Delete image", ...
Table Design
User
id
name
password
Image
id
user_id
filename
description
upload_date
Image_Gallery
image_id
gallery_id
Gallery
id
name
User_Role
user_id
role_id
User_Right
user_id
right_id
Role
id
name
Role_Right
role_id
right_id
Right
id
name
You may want to remove all the things with Right if it is enough to separate user privileges by Role.

Within the tables images and users, you will be referencing the clients id, not the name.
I would create a separate table for the galleries, as clients tend to have new wishes every three month. So you maybe need to add more galleries.
table "galleries"
id
name
table "image_is_in_gallery"
image_id
gallery_id
PRIMARY(image_id, gallery_id)

You might want to consider normalization.
Assuming that usernames are unique - two people can't have the same username, come on - then you can eliminate "id" in the Users table in order to help prevent update/insert/delete anomalies (doing this would almost certainly put Users into BCNF, and likely DKNF - this is a good thing).
Clients is fine. What is the difference between Clients and Users, though? Really... seems similar to me.
Make sure that references are done using foreign key constraints, and I think that should be better.
EDIT:
Based on the new design, I have these suggestions:
Change Clients/Users into three tables:
ClientNames
- ClientID (PK)
- ClientName
ClientUsernames
- ClientID (PK)
- Username
UsernamePasswords
- Username (PK)
- Password
This is safe and says that one Client/User has one name, one Client/User has one Username, and one Username has one Password. I don't see another good decomposition (in the sense that it's going to be in a tight normal form).
You can eliminate one of these tables by eliminating the synthetic "ClientID" key, if you want. There are disadvantages to this, and it may not be possible (some people do have the same name!).
The problem here is that it is likely that ClientID, ClientName, and UserName determine each other in a way that isn't amenable to stuffing them in the same table.

use client id instead of client_name on the images and users table
Add another table, portfolio with at least name and id columns
Add another table, portfolio_images with two columns, image_id and portfolio_id. This will allow the feature mentioned by #Alex in the comments
response to edit
You can do the one image in multiple portfolios by querying PORTFOLIO_IMAGES and JOINing with images or portfolios as necessary. For example, if you want to display the wedding portfolio (psuedo-code)
SELECT filename,...
FROM images img
INNER JOIN portfolio_images pimg on img.image_id = portfolio_images.image_id
WHERE pimg.portfolio_id = <whatever the id is for wedding portfolio>

Related

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.

How to store users's notifications options?

I'm creating a database users. I want to let users to choose notifications they want to receive by email.
Now I have the next columns in table users (boolean type):
notification_comment_photo.
notification_comment_comment.
notification_vote_photo.
notification_vote_comment.
notification_pm.
notification_followed.
notification_news.
What do you think, should I normalise table users and create another table notifications, considering that this table would have one-to-one relationship to table users?
Also I have the same problem with social links (twitter, facebook, google+, etc). Is it better to make a separate table links?
upd. Thanks all, I'll add the separate tables.
It's hard to answer your question, because you're not telling us what problem you're trying to solve.
One issue with your current design is that it requires a schema change for every new type of notification you want to store - if you want to notify users when they've been un_followed, you have to add a column to your users table.
I'd consider a schema like:
TABLE: users
------------------
ID
...
TABLE: notification_types
----------------------
ID
Description
TABLE: user_notifcation_subscriptions
-----------------------------------------
user_id
notification_type_id
subscribed (bool)
You could leave the "subscribed" column out of user_notification_subscriptions and decide that any record linking a user to a notification type means they have subscribed.
This design allows you to add new subscription types without changing the schema. I believe it's similar to the design #Daniel suggests, but he doesn't include the notification_type table, relying instead on name-value pairs. I'm not a fan of this - it can lead to silly, hard-to-find bugs when typos slip into the TYPE column.
You could (and probably should) create a separate table "notification_settings" or something.
ID
USER_ID
TYPE
VALUE
This allows you to easily add notification settings without messing with the database tables. Having a "strict" structure as you suggested sometimes gets in the way in the end and would be harder to expand.
For your social links, you should do the same. Another table named "user_social_accounts"
ID
USER_ID
NETWORK_ID

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.

Database design for user driven website

Assuming I want to have a web application that requires storing user information, images, etc as well as storing status updates or posts/comments would I want to separate tables?
For example if I have a "users" table that contains users information like passwords, emails, and typical social networking info like age, location etc. Would it be a good idea do create a second table("posts") that handles user content such as comments and/or post?
Table one: "users"
UserID
Username
Age
etc.
Table Two: "posts"
PostID
PostContent
PostAuthor
PostDate
etc
Is this a valid organization? Furthermore if I wanted to keep track of media should I do this in ANOTHER table?
Table Three: "media"
ID
Type
Uploader
etc.
Any help is much appreciated. I'm curious to see if I'm on the right track or just completely lost. I am mostly wondering if I should have many tables or if I should have larger less segregated tables.
Also of note thus far I planned on keeping information such as followers(or friends) in the 'users' table but I'm not sure that's a good idea in retrospect.
thanks in advance,
Generally speaking to design a database you create a table for each object you will be dealing with. In you example you have Users, Posts, Comments and Media. From that you can flesh out what it is you want to store for each object. Each item you want to store is a field in the table:
[Users]
ID
Username
PasswordHash
Age
Birthdate
Email
JoinDate
LastLogin
[Posts]
ID
UserID
Title
Content
CreateDate
PostedDate
[Comments]
ID
PostID
UserID
Content
[Media]
ID
Title
Description
FileURI
Taking a look above you can see a basic structure for holding the information for each object. By the field names you can even tell the relationships between the objects. That is a post has a UserID so the post was created by that user. the comments have a PostID and a UserID so you can see that a comment was written by a person for a specific post.
Once you have the general fields identified you can look at some other aspects of the design. For example right now the Email field under the Users table means that a user can have one (1) email address, no more. You can solve this one of two ways... add more email fields (EmailA, EmailB, EmailC) this generally works if you know there are specific types of emails you are dealing with, for example EmailWork or EmailHome. This doesn't work if you do not know how many emails in total there will be. To solve this you can pull the emails out into its own table:
[Users]
ID
Username
PasswordHash
Age
Birthdate
JoinDate
LastLogin
[Emails]
ID
UserID
Email
Now you can have any number of emails for a single user. You can do this for just about any database you are trying to design. Take it in small steps and break your bigger objects into smaller ones as needed.
Update
To deal with friends you should think about the relationship you are dealing with. There is one (1) person with many friends. In relation to the tables above its one User to many Users. This can be done with a special table that hold no information other than the relationship you are looking for.
[Friends]
[UserA]
[UserB]
So if the current user's ID is in A his friend's ID is in B and visa-verse. This sets up the friendship so that if you are my friend, then I am your friend. There is no way for me to be your friend without you being mine. If you want to setup the ability for one way friendships you can setup the table like this:
[Friends]
[UserID]
[FriendID]
So If we are both friends with each other there would have to be 2 records, one for my friendship to you and one for your freindship to me.
You need to use multiple tables.
The amount of tables depends on how complex you want your interactive site to be. Based on what you have posted you would need a table that would store information about the users, a table for comments, and more such as a table to store status types.
For example tbl_Users should store:
1. UserID
2. First Name
3. Last name
4. Email
5. Password (encrypted)
6. Address
7. City
8. State
9. Country
10. Date of Birth
11. UserStatus
12. Etc
This project sounds like it should be using a relational DB that will pull up records, such as comments, by relative userIDs.
This means that you will need a table that stores the following:
1. CommentID (primary key, int, auto-increment)
2. Comment (text)
3. UserID (foreign key, int)
The comment is attached to a user through a foreign key, which is essentially the userId from the tbl_Users table. You would need to combine these tables in an SQL statement with your script to query the information as a single piece of information. See example code
$sql_userWall = "SELECT tbl_Users.*, tbl_Comments.*, tbl_userStatus FROM tbl_Users
INNER JOIN tbl_Comments ON tbl_Users.userID = tbl_Comments.userID
INNER JOIN tbl_UserStatus ON tbl_Users.userID = tbl.UserStatus
WHERE tbl_Users.userID = $userID";
This statement essentially says get the information of the provided user from the users table and also get all the comments with that has the same userID attached to it, and get the userStatus from the table of user status'.
Therefore you would need a table called tbl_userStatus that held unique statusIDs (primary key, int, auto-incrementing) along with a text (varchar) of a determined length that may say for example "online" or "offline". When you started the write the info out from e record using php, asp or a similar language the table will automatically retrieve the information from tbl_userStatus for you just by using a simple line like
<?php echo $_REQUEST['userStatus']; ?>
No extra work necessary. Most of your project time will be spent developing the DB structure and writing SQL statements that correctly retrieve the info you want for each page.
There are many great YouTube video series that describe relational DBS and drawing entity relational diagrams. This is what you should look into for learning more on creating the tye of project you were describing.
One last note, if you wanted comments to be visible for all members of a group this would describe what is known as a many-to-many relationship which would require additional tables to allow for multiple users to 'own' a relationship to a single table. You could store a single groupID that referred to a table of groups.
tbl_groups
1. GroupID
2. GroupName
3. More group info, etc
And a table of users registered for the group
Tbl_groupMembers
1. membershipCountID (primary key, int, auto-increment)
2. GroupID (foriegn key, int)
3. UserID (foriegn key, int)
This allows users to registrar for a group and inner join them to group based comments. These relationships take a little more time to understand, the videos will help greatly.
I hope this helps, I'll come back and post some YouTube links later that I found helpful learning this stuff.

Database user scenario with multiple type of user

I am designing a database for a Yii project, the scenario is a user will be ONLY one of the following type: employee, company and business owner person (i.e. the owners who manage companies and employees - super admin - I broke the many to many relationship that's why I call the table "business_owner_person"). Below is how I designed my database in MySQL:
USER
id,
username,
password,
active
COMPANY
id,
name,
contact_no,
contact_name,
address...
user_id (FK)
EMPLOYEE
id,
first_name,
surname,
address,
email...
company_id (FK)
user_id (FK)
BUSINESS_OWNER_PERSON
id,
name,
email,
position...
user_id (FK)
I am just wondering if there is a better/efficient way to design this scenario so that Yii won't have the problem to fetch the correct additional informations for user.
It's difficult to make suggestions without knowing a little more about the business, but it seems like you have too much redundant information.
Splitting out the user is good, since any of these types of people can be a user. I would probably put the common information, name, email into the user field, maybe even the address and position.
Then what it looks like you want is that a user can have one or more roles, where the role controls their level of access. This could be as simple, to start out with as a role_id columns in the DB table, or it could be a separate table, user_id, role_id.
Now, all that being said, it's difficult to make suggestions without more information. Do you need to isolate users by company? Will there be a lot of companies? How many business owners are you looking at having?