Suggestions of users to follow - mysql

I'm working on social media site, but I can't get a logic that how do I give a list of suggested users to follow.
Users table :-
id | name | username | password
Relationship table :-
id | followee | follower
where followee and follower are the foreign keys to users table.
I tried some sql joins and also put some logic in backend but that didn't worked.
Here is what I tried :-
select u.id, u.name from users u, relationship r on u.id = r.follower where u.id != (user_id) and r.follower != (user_id)
Here in user_id I have to pass the id of the logged in user, so that I want to return the list of users whom current user don't follow and if relationship table is empty then it must return all the users from users table except current user.
Here I also want to return distinct values from users table and follower column.
Here image I have provided an image of sample data.
If current user id 187 follows all users then it must return empty data.
if current user id 188 doesn't follow anybody then it must return data of 187 and 198.

You want to use NOT IN:
SELECT u.id, u.name FROM users u
WHERE u.id NOT IN (
SELECT r.followee FROM relationship
WHERE r.follower = (user_id)
) AND u.id != (user_id)

Related

Join between two tables on multiple column

I am wondering if I can have join between two tables but on different columns? Let me explain because it is different with most of the cases that I've seen...
I have a table for all the messages between users and each user has a unique user id. so In the first table I have:
Tx User Id .......... Rx. User Id .......... Date ............ Message
and in user tables I have
user Id .............. User name
Can I have a join query that gives me
Tx User "Name" ........... Rx. User "Name: ....... Date ....... Message
The problem is that in my join apparently I can only define
SELECT messages.* users.name
FROM messages JOIN
users
ON messages.RxId = users.id OR messages.TxId = users.id
which is only 1 field, but as I explained above I need 2 field as Rx user name and Tx. User Name based on which id in my messages table is matched.
Thanks a lot in advanced.
You want two joins. And for this you need to learn about table aliases (a good thing):
SELECT m.*, urx.name, utx.name
FROM messages m LEFT JOIN
users urx
ON m.RxId = urs.id LEFT JOIN
users utx
ON m.TxId = utx.id;

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;

MySQL - Get count of users that have a "user-contact"

Consider the three tables in the following Schema SQL Fiddle.
This mini-model represents a simple example of a database I'm working on .
The Users table has 4 attributes, the user_id (primary key auto_increment), the country_id which is a foreign key referencing the Country table, the user_msisdn which is the phone number of the user, and the username.
The Contacts table has 3 attributes, the contact_id (primary key auto_increment), the user_id which is a foreign key referencing the Users table, and the contact_msisdn which is the user contact's phone numbers (the phone numbers on your phone contacts list).
The relation between the Users table and the Contacts table is many-to-many, a user can have many contacts, and a contact can be found in any user's contacts list.
Requirements:
For each country, get the count of users that have at least one "user-contact", where a "user-contact" is a contact that is a user, and the count of users that don't have any "user-contact".
E.g., For country = 'Sweden' (country_id = 3), the user_id = 3 has two contacts in the Contacts table that are considered "user-contact" with (msisdn = '+220011223344' & '+224433221100'). So the query results that I want: Sweden has 1 user (user_id = 3) that has at least one "user-contact" and zero users that have no "user-contact", and so on for each country.
Try this:
SELECT c.country_id,
COUNT(DISTINCT CASE WHEN u2.user_id IS NOT NULL THEN u.user_id END) as has_contact_that_is_user ,
COUNT(distinct CASE WHEN u2.user_id is null AND u.user_id IS NOT NULL THEN u.user_id END) as has_no_contact_that_is_user
FROM Country c
LEFT JOIN users u
ON(c.country_id = u.country_id)
LEFT JOIN contacts co
ON(co.user_id = u.user_id)
LEFT JOIN Users u2
ON(u2.user_msisdn = co.contact_msisdn)
GROUP BY c.country_id
Fiddle

Mysql social network follower query

I am making a social networking application and now i am trying to make the database for the application.
I have 2 tables user table and follower table. Table structure look like this
user table follower table
---------------- ----------------
userid (int) userid
username follower id
----------------
I am trying to list all followers of a user. I need the followers username in the result. I don't know how to do it. Any help would be much appreciated. thanks.
Assuming "follower id" (hopefully not the actual column name) is a foreign key reference to user(userid), a simple join query should suffice
SELECT u.userid, u.username
FROM `follower table` f
INNER JOIN `user table` u on f.`follower id` = u.userid
WHERE f.userid = :userid -- the ID of the user who's followers you're after

Why is this adding all rows? Insert only when exists?

I'm trying to insert a row into mentions when a username exists in the users table.
INSERT INTO mentions (user_id)
SELECT USER_ID
FROM users
WHERE EXISTS (
SELECT USER_ID FROM users
WHERE USERNAME LIKE 'mike'
);
However, the above query is adding ALL user_ids into the mentions table -- all 1 million of them. What am I overlooking here?
Users table schema
USER_ID | USER_NAME | USER_STATUS
1 | mike | active
2 | brian | active
mentions table schema
MENTION_ID | COMMENT_ID | USER_ID
I have a comment "#mike have you talked to #john lately?" and I'm parsing for the mentions. If mike is found in the user's table, I want to insert it into the mentions table along with the comment_id.
exists needs to have a correlation to the outer select so something like this
INSERT INTO mentions (user_id)
SELECT u.user_id
FROM users u
WHERE EXISTS
( SELECT 1 FROM mentions m
WHERE u.user_id = m.user_id
AND m.username = 'mike'
);
you can also use IN
INSERT INTO mentions (user_id)
SELECT u.user_id
FROM users u
WHERE u.user_id IN
( SELECT m.user_id FROM mentions m
WHERE m.username = 'mike'
);
NOTE:
I removed the LIKE 'mike' and just changed it to = 'mike'... LIKE is used when you need to match partial strings... you can easily do it with = if you are looking for the whole string.
if you want to find a partial string then you should include wildcards like so LIKE "%mike%"
EDIT:
with your most recent edit you are trying to do a subquery when you dont need one.
INSERT INTO mentions (comment_id, user_id)
VALUES
(your_comment_id,(SELECT u.user_id FROM users uWHERE u.username = 'mike'));
However, it seems like you should have some sort of dependency between the tables.. can you post the table schemas?
Are you sure USERNAME is in the table mentions?
Maybe you just need:
INSERT INTO mentions (user_id)
SELECT USER_ID
FROM users
WHERE USERNAME LIKE 'mike'