mysql query help to find mutual friends on social networking site - mysql

I have a database table called users with a primary key of user_id for each user.
I also have a table called friends with two fields, user_id and friend_user_id.
The user_id field is always the lowest of the two user_id's in order to avoid duplicate entries.
Say I have two users in mind, (lets say user id 1 and user id 4 although they could be anything).
How would I return all rows from the users table for users that are friends with user 1 and user 4 (i.e mutual friends)?

I will give you the recipe:
Find all friends of user 1
Find all friends of user 2
Intersect them and the result will be the mutual friends.
Much like this:
UPDATE: Here's the query:
select f.friend_user_id from friends f where f.friend_user_id in (
select friend_user_id from friends where user_id=<id_of_user_a>)
and f.user_id=<id_of_user_b>
The ids returned by above query will be the id of all the users that are mutual friends of user_a and user_b. If you want to get all the details (name, etc) about those users, then do this:
select f.friend_user_id,u.* from friends f inner join users u
on u.user_id=f.friend_user_id
where f.friend_user_id in (
select friend_user_id from friends where user_id=<id_of_user_a>)
and f.user_id=<id_of_user_b>

SELECT friends.friend_user_id FROM user, friends
INNER JOIN friends ON friends.user_id = user.user_id
WHERE user.user_id = 1
AND friend.friend_user_id
IN (SELECT friends.friend_user_id
FROM user, friends
INNER JOIN friends ON friends.user_id = user.user_id
WHERE user_id = 4)

Related

How to make many to many relationship table efficient for SELECT queries in MySQL?

A user can have many interests.
An interest can be interested to many users.
My database looks like that:
Users table:
id - primary key,
name,
email,
Interests table:
id - primary key,
title
Users_To_Interests table:
id - primary key,
user_id(id from users table)
interest_id(id from interests table)
How can I improve Users_To_Interests table to be able to pick all users who have the same interest efficiently? user_id and interest_id columns don't have indexes or keys. If I need to add them, please show me how can I make that.
Edition 1: For example,
user1 has interests : interest1, interest2, interest3;
user2 has interests : interest3, interest4;
user3 has interests : interest3, interest5;
user4 has interests : interest4;
If I want to get all users who have interest1, I should receive user1;
If I want to get all users who have interest2, I should receive user1;
If I want to get all users who have interest3, I should receive user1, user2, user3;
The query to get users for interest #3 is very simple (use IN or EXISTS). With an index on users_to_interests(interest_id, user_id) this should be very fast.
select *
from users
where id in (select user_id from users_to_interests where interest_id = 3);
Here is a query which would find all users having interests 1 and 2. It should be clear how to generalize this to any number of interets. The subquery aggregates over users and finds those users who have the interests we want. We then join this back to the Users table to get the full information for each user.
SELECT
t1.*
FROM Users t1
INNER JOIN
(
SELECT ui.user_id
FROM Users_To_Interests ui
INNER JOIN Interests i
ON ui.interest_id = i.id
WHERE i.title IN ('interest2', 'interest3')
GROUP BY ui.user_id
HAVING COUNT(DISTINCT i.id) = 2
) t2
ON t1.id = t2.user_id;

A complex data not sure how to explain it

Hi I have a table called Users and a table called friends, friends table have two data types UserID and FriendID, (foreign key of both data types to primary key of the Users table),
I need to give an ID and find a list of that persons friends'name, I am not sure if I have designed the tables wrongly or I should rewrite the query.
my query is as following, (so far it just shows the details of first matched person)
SELECT Users.Name
FROM Users
WHERE Users.ID = SELECT Friends.UserID
FROM Friends,Users
WHERE Users.ID = (Select Users.ID
From Users
WHERE Users.Username = 'John')
Try this:
SELECT Users.Name FROM Users WHERE Users.ID IN -- Get names that belongt to ID's
(SELECT FriendID FROM Friends WHERE UserID = -- All ID's of the Friends of
(SELECT UserID FROM Users WHERE Name = 'John')) -- Johns ID
I've solved it by changing the first = to IN
is this you want to achieve ??
User
UserID (PK)
Name
Friend
FriendID (PK)
UserID (FK)
select User.Name from User u join Friend f on f.UserID = u.UserID where Name = 'John'

MYSQL/PHP table design for friends table/query to select friends

For a social network site, I have a table with the ids of the inviter and the invitee and the status of the invitation ie accepted or not. According to what I've read, this seems to be best practice for a friends table.
Table friends
id | inviterid |inviteeid |status
however, for a given userid, I want to display all the "friends" the person has including their names. I can get a list of records of relationships with a simple query
Select * from friends WHERE inviterid = '33' or inviteeid = '33'"
But, this does not translate easily into a list of friends, since the friends could be either inviters or invitees so the field will be different depending on who invited whom.
Is there a better table design for a friends table? Alternatively, is there a sql syntax that would select friends who can be either inviters and invitees. Ultimately, I need to do a join to another table that has the users names.
You have a user table with below colums
userId|name|...
and your friend table
id | inviterid |inviteeid |status
if you want to find friends of a user that this user invited themes you can use below query!
select id, status from friend_tbl inner join user_tbl on user_tbl.id=friend_tbl.inviterid;
or if you want to get friend of this user that themes invitee his/her you can use below query:
select id, status from friend_tbl inner join user_tbl on user_tbl.id=friend_tbl.inviteeid;
I hope these can help you and i can understand your purpose!
Use union to get two kinds of friendS together, then you can join the results with username table.
Select inviterid as friend_id, status from friends where inviteeid = 33
Union
Select inviteeid as friend_id, status from friends where inviterid =33
I personally would just prefer to have two tables for this case, friend table and invite table
Friend Table
id | userid | friendid
So for selecting friends would be just
SELECT friendid FROM friend_table WHERE userid = 33
Invite Table
id | inviterid | inviteeid | status
For changing the status of invite table once the user approves, and insert new row to friend table
UPDATE invite_table SET status = 'accepted' WHERE inviterid = 33
INSERT INTO friend_table (`userid`, `friendid`) VALUES (33, $friendid)

Get 2x same table's column 1 result

I have a users table and a friends table.
I want to get the friendships of 1 user, but getting both user info in results.
For example, let's say I have these tables:
- users (_id_, username, firstname, lastname)
- friends (_#id1, #id2_)
Here are some data:
- users (1, foo, Foo, BAR)
(2, john, John, DOE)
- friends (1, 2)
If I query fiendship WHERE id1 = 1 OR id2 = 1, I know that with a JOIN I can get for each row, the user data. But how to get in 1 result (1 row) both users data?
SELECT
u1.*,
u2.*
FROM
friends
JOIN users AS u1
ON friends._#id1=u1._id_
JOIN users AS u2
ON friends.#id2_=u2._id_
SELECT u1.*, u2.*
FROM users u1
JOIN friends f1
ON u1._ID_ = friends._#id1_
JOIN users u2
ON u2._ID_ = friends._#id2_
Each row will contain all the info from one user, and then all the info from the second user. You might want to replace that first JOIN friends f1 with LEFT OUTER JOIN friends f1 to also display a row for users without friends.
Careful: a user with multiple friends will show multiple rows. There is no automatic way in MySQL to pivot these rows to columns. You can however GROUP on the u1._ID_, and then use the GROUP_CONCAT function to display the friends information.

MySQL inner join with 2 columns

I have one table users with 2 fields : id , name and another table friends with 2 fields : userid1 userid2 .
So this means userid1 is friend with userid2 . I want , with one inner or left join to show this :
userid1 name(got from users table) is friend with userid2 name(got from users table)
something
SELECT * FROM friends INNER JOIN users ON friends.userid1 = users.id AND friends.userid2 = users.id but this is not working.
Any good query with good explanation please?
If, for example I have the next details in the users table :
ID : 1 NAME : FinalDestiny
ID : 2 NAME : George
and the next details in the friends table :
ID1 : 1 ID2 : 2
So this means 1 is friend with 2.
I need with one query to get the name of 1 and the name of 2 and to echo that they're friends
FinalDestiny is friend with George
I know that you specify that you want this done with one join, but it looks to me like you need two. I believe this query will give you what you need:
SELECT u1.Name, u2.Name
FROM Users u1, Users u2, Friends f
WHERE u1.id = f.userid1 AND u2.id = f.userid2
I am joining the Users table with the Friends table with on Users.id = Friends.userid1. Then, I am joining this new table with the Users table on (new table).userid2 = Users.id. This results in a table with 4 columns. These columns are the original 2 columns of the Friends table in addition to 2 columns for the names of the friends. u1, u2, and f and referring to the three tables that were joined. The users table was joined with the friends table twice. u1 is the copy of the Users table that was joined on Friends.userid1 = User.id. u2 is the copy of the Users table that was joined on Friends.userid2 = User.id.
From this table with 4 columns, I am selecting only the names of the friends.
Let me know if more explanation is needed.
You check on a user being a friend of itself. Use OR in your select to match user's friends:
SELECT * FROM friends INNER JOIN users ON friends.userid1 = users.id OR friends.userid2 = users.id
If, for example I have the next details in the users table :
ID : 1 NAME : FinalDestiny
ID : 2 NAME : George
and the next details in the friends table :
ID1 : 1 ID2 : 2
So this means 1 is friend with 2.
I need with one query to get the name of 1 and the name of 2 and to echo that they're friends
FinalDestiny is friend with George