Friendship table - mysql

I've got a table called users which contains the users on my webpage. The users can make a friendship where user 1 request user 2 for a friendship.
The way it is working now is, that when user 1 sends the request I create a row in the friendship table which contains the two foreign keys: user_id_from and user_id_to and a field called status which can either be 0 (the request is pending), 1 or 2 either the user_id_to has accepted or declined the friendship request, respectively. And lastly the status can be 3 which indicates that one of the users have deleted the friendship.
Is this the right approach, or should I create a temporary table which contains all the pending request, and then (if the request is accepted) it is inserted into a friendship table?

From a logical perspective, what you're doing is correct, since I would personally consider a pending friendship request a form of friendship which isn't confirmed.
From a design perspective, I'm not sure how you would create a temporary table each time the user needs to see his list of friendship requests. If the table isn't temporary, you would have a table named confirmed_friendships and pending_friendships.
I highly suggest that you keep both in the same table, unless there will be lots of columns which are specific to pending_friendships and not available for confirmed_friendships, or vice versa.

Related

Combine two sources of friends relationships in one table

I have mobile app with users. Everything is simple - each user have id and name.
Users Table
id name
1 John
2 Dave
3 Jack
Some of this users are friends and the main purpose of my question - finding the best way to rebuild friendship table that looks like (the only rule is user_id_1 < user_id_2)
Friendship table
id user_1_id user_2_id
1 1 2
2 1 3
3 2 3
How I know that users are friends? I take this information from different sources (social network A, social network B). So if two users are friends at least in one of two social networks - they are friends in my app.
Right now I am recreating friendship table each day:
Take each user, create empty array NewFriends for this user
Erase all records containing his id from friendship table
Find all his friends in network A (A-friends)
For each of A-friends - find they ids in my app and add them to NewFriends array
Find all his friends in network B (B-friends)
For each of B-friends - find they ids in my app and add them to NewFriends array if they don't already exist there
Delete all friendship records from Friendship table that are not mentioned in NewFriends array
Insert all friendship records from NewFriends array to Friendship table that were not existed there before
How can I solve this task better?
First,
you can use the only one table of the 2 networks (instead of using A-friends table and B-friends table)
and when select you could use distinct keyword
steps will be :
Take each user
Erase all records containing his id from friendship table
Find all his friends in network A and add it to (Temp-friends)
Find all his friends in network B and add it to (Temp-friends)
For each distinct of Temp-friends - add records in NewFriends table
Delete all friendship records from Friendship table that are not mentioned in NewFriends array
Insert all friendship records from NewFriends array to Friendship table that were not existed there before
You can use set data type instead array. The reason to use set is set doesn't contain duplicate values.
Use two sets oldFriendships and newFriendships.
From friendships table load data to oldFriendships
Create new newFriendships
2.1. From network A find all friends for the user and add it to the newFriendships
2.2. From network B find all friends for the user and add it to the newFrindships
Update friendship table
3.1 Find oldFriendships complement newFrindships - this is removed friendships, delete these values from friendship table
3.2. Find newFrindships complement oldFriendships - this is added friendships, add these values to friendship table
Here is wikipeda article about complement

How to design table when have two table reference single column in another table

I am confusing about how to design table when have two table reference single column in another table.
For example, I have two type of user ( lets call them user1 and user2 ) because these two type user have multiple different information so I create two table for each of them, and each user have one account to login to system. So I create a table call account and let two table user1 and user2 reference to ID in table account. So when I have one account and I want to know which one this account belong to. It's quite inconvenient because I have to look for in two table.
Does it have solution for this problem ?
If you have an entity user, create just one table user for them.
A user is a user, no matter if he has some special role. There will be some common fields for all users, e.g. a name.
table user:
user id
user name
age
homepage
To have specific information for different types of users, you create specialisation table with information about these roles:
table role1:
user id
roleinfo1
roleinfo2
table role2:
user id
roleinfo3
roleinfo4
roleinfo5
This way, a user can have multiple roles at the same time, but you can of course limit them to just one.
If a user can only be one of those roles (that's called disjunct), you have the additional statndard way to add a column role to your user-table and put all the information side-by-side in the user table, leaving the ones that don't belong to the user-role null:
table user:
user id
user name
age
homepage
roletype
roleinfo1
roleinfo2
roleinfo3
roleinfo4
roleinfo5
Even if the user can belong to multiple classes and in case there is no overlap between the additional columns, you can of course use the last approach and add multiple flags (e.g. columns istype1 and istype2), though this is a non-standard-approach.
Update Just to clarify how you use the first solution: every user has an entry in table user, e.g. with user id = 1. This also makes sure that no user of roles user1 and user2 can have the same user id.
User id in the role tables is both primary key and a foreign key of the user table.
To make that user a user of role 1, you then add an entry to table role 1 with user id = 1. If he is (also) a user of role 2, you add an entry to table role2 with user id = 1.
You can join the tables to get the "whole" picture,
select * from user
left join role1 on user.`user id` = role1.`user id`
left join role2 on user.`user id` = role2.`user id`
This will, apart from the double id columns (that will basically can be treated as the marker istype1, istype2 in the comment to the seconds solution) and the missing role-column look exactly like the second method with just one table.
To check if user with user id = 1 is of role 1, you can check if role1.user id is null in this query, or check if user id = 1 is in table role1. To e.g. list all data for just role 1, you can use
select * from user join role1 on user.`user id` = role1.`user id`
(it uses a join instead of the left join, since and entry for role 1 has to exist).
In most cases you don't even need the specialized data, so you can just join your account-table with the user-table. In any case, you never have to worry about checking two tables (or even more, if you decide to add a 3rd kind of user).
Whats the point of the account table? If each user has one account, why don't you store the account columns in the User table.
Furthermore you can still make a parent user table for the columns they share and then make childtables for the specific users.
for example
Parent: User
Children: Employee/Customer

MySQL update table 1 with table 2 data

Sorry for the ambiguous title.
I have two tables:
table 1: mailing_email
table 2 (dynamic table but for now is): membership
table 1 contains a list of all email accounts in the database and few ancillary fields such as name. It also has a column called communicate.
communicate is basically my terminology for subscribed. Any unsubscribe link will set communicate to false.
Both mailing_email and membership have a email and communicate column.
I need to write a query where the following happens:
mailing_email.communicate gets updated to the current status of membership.communicate where mailing_email.email = membership.email. If an email exists in mailing_email which does not exist in membership, the communicate field stays the same.
How would i go about doing this the fastest possible way? Each table will have thousands of rows this sync command would run often.
MySQL offers an update join syntax:
UPDATE mailing_email
JOIN membership ON mailing_email.email = membership.email
SET mailing_email.communicate = membership.communicate

MySQL - Table Implementation

I had to implement the following into my database:
The activities that users engage in. Each activity can have a name with up to 80 characters, and only distinct activities should be stored. That is, if two different users like “Swimming”, then the activity “Swimming” should only be stored once as a string.
Which activities each individual user engages in. Note that a user can have more than one hobby!
So I have to implement tables for this purpose and I must also make any modifications to existing tables if and as required and implement any keys and foreign key relationships needed.
All this must be stored with minimal amount of storage, i.e., you must choose the appropriate data types from the MySQL manual. You may assume that new activities will be added frequently, that activities will almost never be removed, and that the total number of distinct activities may reach 100,000.
So I already have a 'User' table with 'user_id' as my primary key.
MY SOLUTION TO THIS:
Create a table called 'Activities' and have 'activity_id' as PK (mediumint(5) ) and 'activity' as storing hobbies (varchar(80)) then I can create another table called 'Link' and use the 'user_id' FK from user table and the 'activity_id' FK from the 'Activities' table to show user with the activities that they like to do.
Is my approach to this question right? Is there another way I can do this to make it more efficient?
How would I show if one user pursues more than one activity in the foreign key table 'Link'?
Your idea is the correct, and only(?) way.. it's called a many to many relationship.
Just to reiterate what you're proposing is that you'll have a user table, and this will have a userid, then an activity table with an activityid.
To form the relationship you'll have a 3rd table, which for performance sake doesn't require a primary key however you should index both columns (userid and activityid)
In your logic when someone enters an activity name, pull all records from the activity table, check whether entered value exists, if not add to table and get back the new activityid and then add an entry to the user_activity table linking the activityid to the userid.
If it already exists just add an entry linking that activity id to the userid.
So your approach is right, the final question just indicates you should google for 'many to many' relationships for some more info if needed.

Design of MySQL DB to avoid having a table with mutually exclusive fields

I'm creating a new DB and I have this problem: I have two type of users that can place orders: registered users (that is, they have a login) and guest users (that is, no login). The data for registered users and guest users are different and that's why I'm thinking of using two different tables, but the orders (that share the same workflow) are all the same, so I'm thinking about using only one table.
I've read here and here (even if I don't understand fully this example) that I can enforce a MySQL rule to have mutually exclusive columns in a table (in my case they'd be "idGuest" and "idUser") but I don't like that approach.
Is there a better way to do it?
There are several approaches, which depends on the number of records and number of unique fields. For example, if you would say they differ in only two fields, I would have suggested that you just put everything in the same table.
My approach, assuming they differ a lot, would be to think "objects":
You have a main user table, and for each user type you have another table that "elaborates" that user info.
Users
-----
id,email,phone,user_type(guest or registered)
reg_users
---------
users_id, username,password etc.....
unreg_users
-----------
user_id,last_known_address, favorite_color....etc
Where user_id is foreign key to users table
Sounds like mostly a relational supertype/subtype issue. I've answered a similar question and included sample code that you should be able to adapt without much trouble. (Make sure you read the comments.)
The mildly complicating factor for you is that one subtype (guest users) could someday become a different subtype (registered users). How you'd handle that would be application-dependent. (Meaning you'd know, but probably nobody else would.)
I think I would have three tables :
A user table, that would contain :
One row for each user, no matter what type of user
The data that's present for both guests and registered
A field that indicates if a row corresponds to a registered or a guest
A guest table, that would contain :
One row per guest user,
The data that's specific to guests
And a registered table, that would contain :
One row per registered user,
The data that's specific to registered users
Then, when referencing a user (in your orders table, for example), you'd always use the id of the user table.
What you are describing is a polymorphic table. It sounds scary, but it really isn't so bad.
You can keep your separate User and Guest tables. For your Orders table, you have two columns: foreign_id and foreign_type (you can name them anything). The foreign_id is the id of the User or Guest in your case, and the content of the foreign_type is going to be either user or guest:
id | foreign_id | foreign_type | other_data
-------------------------------------------------
1 | 1 | user | ...
2 | 1 | guest | ...
To select rows for a particular user or guest, just specify the foreign_type along with the ID:
SELECT * FROM orders WHERE foreign_id = 1 AND foreign_type = 'guest';
The foreign key in the Orders table pointing back to the Customer entity that placed the order is typically a non-nullable column. If you have two different Customer tables (RegisteredCustomer and GuestCustomer) then you would requiree two separate nullable columns in the Orders table pointing back to the separate customer tables. What I would suggest is to have only one Customers table, containing only those rows (EDIT: sorry, meant to write only those COLUMNS) that are common to registered users and guest users, and then a RegisteredUsers table which has a foreign-key relationship with the Customers table.