SQL Friends List Query - mysql

I am new to this database SQL language so I will try to make it as simple as possible. (I am using MySQL Workbench)
I have a table for User and I want multiple users to be friends with each other. For that I created the friends table where it has a user_id and friend_user_id. So let's say we have (1,2), (2,3). I want this to be read as: "2 is friends with 1 and 3, 1 is friends with 2, 3 is friends with 2". So when inserting on this friends table I never do something like this (1,2),(2,1). I'm looking for a procedure that by receiving an user_id as parameter to return all his friends whether they are in the user_id column or the friend_user_id column. For example, if I look for user 2's friends it should appear 1 column with 1 and 3, because 1 and 3 are friends with 2.
To be more specific, when I call get_friends(2) it should appear
[1]
[3]
Even though these are in different columns on the friends table.

You can use IN to check if either column is equal to the ID of the user you want to look up and a CASE ... END to take the column which is not equal to the ID of the user you want to look up.
SELECT CASE
WHEN user_id = 2
THEN user_friend_id
WHEN user_friend_id = 2
THEN user_id
END friend
FROM friends
WHERE 2 IN (user_id, user_friend_id);
Alternatively you could use a UNION ALL approach, which might perform better as it can use indexes on user_id or user_friend_id.
SELECT user_id friend
FROM friends
WHERE user_friend_id = 2
UNION ALL
SELECT user_friend_id friend
FROM friends
WHERE friend_id = 2;
But this is only better if there are such indexes. If there aren't, it may need two scans on the table opposed to the first approach only needing one. So it's worse in that case.

Use UNION ALL to get all friends, parameterize this query:
select friend_user_id as friend_id from friends f where f.user_id = 2 --parameter
union all
select user_id as friend_id from friends f where f.friend_user_id = 2 --parameter

Related

How to select from two tables with IF?

I have 2 table in my DB, first is users, and second is friends.
In the users tables I have a column named `friend' this columns have a random ID of each one, and this ID you used for calling someone to subscribe with your URL.
but if an old person want to become your friend I add other table named friends
content the random ID + ID_USER
now, I want to SELECT * FROM users, friends WHERE users.friends = 'BlaBla' OR friends.RANDOMID = 'BlaBla'
I try with this code, but I doesn't work, it's give all persons having the random
in calling friend
SELECT *
FROM users, friends
WHERE users.Role = "User"
AND users.call = :random
OR (users.ID = friends.ID_USER
AND friends.random = :random)
Any solution?

SQL INSERT INTO two tables from one table

Consider the app Tinder and the following numbers:
(User_id, target_id)
(1,2);
(2,1);
(3,5)
(5,3);
(4,1);
This means that 1 and 2 have matched, and 3 and 5, but not 4 and 1.
Now for my question. I have two tables in MySQL database currently. User and Likes.
Where User has bunch of values, but id is the important one (image 1).
Likes has two values: user_id and target_id (image 2).
How should I approach getting the data from User into the columns of Likes? This should result in the target_id and user_id of Likes having the same values as idof User. Am I even going at this correctly?
I know that one has a bunch of columns, and the other has two, and that is where I can't figure out any more.
Your question is kind of vague. Actually I don't know if you want to filter out the non-paired users or you just wanna to include the users info to the "Like". I think you want to find which user pairs like each other.
to do so you can use a query like this:
CREATE TEMPORARY TABLE LikeEachOther(
SELECT DISTINCT‌ L1.user_id, L1.target_id
FROM Likes L1, Likes L2
WHERE‌ L1.user_id = L2.target_id and L2.user_id = L2.target_id
);‌‌‌
SELECT *
FROM LikeEachOther LEO, User U1, User U2
WHERE U1.User_id = LEO.USer_id and U2.User_id = LEO.target_id

How do i get relationships between users?

I have a table called users, that looks like this for example:
Table: users
username id
Simon 6
Ida 7
And a relationships table
Table: Relationships
me partner
6 7
Now for every relationship that is created the me and partner columns will get the id depending on which one of the users sent the request.
If Ida sends a request to Simon, the column looks like this: me: 7 partner: 6
because Ida is id number 7 and Simon is number 6.
But if Simon sends a request then the columns looks like this: me: 6 partner: 7
What i want to do is to write a query that will get the right id from the relationships table for every user with a relationship, and then use the id to Join the users table and get the partners username and print it out.
My problem is that the columns Me and Partner can have different values depending on which of the 2 users sended the request first.
How do i write a query that prints out the right information for each and every user and give them the right id of their partner?
How the output should look like:
From simons point of view*
: You are in a relationship with Ida.
From Idas point of view *
: You are in a relationship with Simon.
I want to offer an alternative.
Join the user table to the relationship table either on the me column or the partner column.
Then join the user table back onto the relationship table using the same criteria.
SELECT u.username,
FROM users u
JOIN relationships r ON u.id = r.me OR u.id = r.partner
JOIN users u2 ON r.me = u2.id OR r.partner = u2.id
WHERE u.id = 'THE USER YOU CARE ABOUT'
Untested. If you throw up some CREATE TABLEs and INSERT INTOs we can all have a play.
If you want to get all users which have a relationship with some user (ex.: id:2) you specify, I would use something like this:
SELECT id, username
FROM user,
(SELECT receiver_id as rel_id FROM relationship WHERE sender_id=2 union
SELECT sender_id as rel_id FROM relationship WHERE receiver_id=2) tab
WHERE id=rel_id
The inner statement means you are selecting all the relationships in which 2 was the sender and all the relationships in which 2 was the receiver and stacking them in the same column (union).
After that, the table user is used to get the user name from the id.
Select username as username,
(select username name from users uSubq where uSubq.id = r.partner) as partnername
from users u join relationships r on u.id=r.me
UNION
Select username as username,
(select username name from users uSubq where uSubq.id = r.me) as partnername
from users u join relationships r on u.id=r.partner;
Here is the test for the query: Sql Fiddle
If either Ida sent request to Simon or the reverse but not both, use UNION ALL for better performance.

SQL - Is it good practice to include a lot of OR operators(like 1000 or more) to build follow system on my site?

I'm making a following system in my site. For example, a user follows 500 people and when that user goes to the main page, it will show messages that is posted from those 500 people. And I will make a query like:
SELECT UserComments FROM comments_table
WHERE UserName = user1 OR user2 OR user3(...)
ORDER BY PostDate DESC.
The problem is, I want to fetch comments from users that is followed, and I want to fetch them with or operator, but I have to include a lot of or operator in between of usernames. Is it good practice to add a lot of or operators?
What should I do? I'm using MYSQL.
You're better off storing these relationships in a table and joining to the table per user.
So you have a User table with an ID. A Following table with LoggedInUserID and FollowedUserID. Then join through the Following table to get comments. Insert 1 record into Following for each User the LoggedInUser is following. This way you keep track of the relationships between users and make good use of the indexes on these tables.
SELECT comments.UserComments FROM Following
INNER JOIN comments on comments.UserID = Following.FollowedUserID
WHERE Following.LoggedInUserID = UserID;
User
UserID Field1 Field2
1 "Stuff" "OtherStuff"
2 "More" "Blah"
3 "And" "Blerg"
Following
LoggedInUser FollowedUserID
1 2
1 3
2 1
3 2
I think you should use IN in this case:
SELECT UserComments FROM comments_table
WHERE UserName IN (user1, user2, user3, .... userN)
ORDER BY PostDate DESC
And many operators OR will bad affect on performance

MySQL - 2 way query check

I am implementing "Add Friend" in my web app, so users could add other users as fiends.
We have 2 tables: tbl_users and tbl_relations, tbl_users have an unique ID for the registered users and tbl_relations will store the users which are friends, for example some rows in tbl_relations are:
id user_id_1 user_id_2
1 4 6
2 4 8
3 8 23
4 12 84
5 3 4
...
In the above results, the id is the unique id for the tbl_relations, user_id_1 is foreign key to tbl_users and user_id_2 is foreign key to tbl_users, now imagine we want to query and check if user with id "4" is friend with user with id "9" or not, here we need to send the query in 2 ways, I mean:
SELECT * FROM tbl_relations WHERE (user_id_1 = '4' AND user_id_2 = '9') OR (user_id_1 = '9' AND user_id_2 = '4')
The above query seems a little weird to me, there should be another way for implementing this I guess, maybe a different database structure?
Or another query, we want to get the mutual friends between users with id "4" and "8", how I'm supposed to get the mutual friends in this scenario? is there any better database structure for this?
I would appreciate any kind of help.
I would de-normalize the relation such that it's symmetric. That is, if 1 and 2 are friends, i'd have two rows (1,2) and (2,1).
The disadvantage is that it's twice the size, and you have to do 2 writes when forming and breaking friendships. The advantage is all your read queries are simpler. This is probably a good trade-off because most of the time you are reading instead of writing.
This has the added advantage that if you eventually outgrow one database and decide to do user-sharding, you don't have to traverse every other db shard to find out who a person's friends are.
If you do it this way you'll have to check for duplicates every time you update. Why not have
user_id1 friend_id
and then query as
select * from tbl_relations where user_id1 in (4,9)
This still seems odd at it implies that 'friend' relations are one-way.
To get the 'mutual' friends - if you do it this way -
select * from tbl_relations t0
join tbl_relations t1 on t0.friend_id = t1.friend_id
where t0.user_id1 = ? and t1.user_id1 = ?