SQL select many to many relationship - mysql

I've the following schema:
Users
-----
id
name
Conversations
-------------
id
other
Partecipants (join table)
------------
id
user_id
conversation_id
other
An user can have many conversations and a conversation belongs to many users.
I need to select all the conversations of an user with a subset of other users.
My try is (do not work):
SELECT *
FROM `conversations`
INNER JOIN `participants` ON `conversations`.`id` = `participants`.`conversation_id`
WHERE `participants`.`user_id` = 1
AND (participants.user_id IN (4,6))
GROUP BY participants.conversation_id
Any idea?

Hmmm. Here is a method using group by and having:
select p.conversation_id
from participants p
group by p.conversation_id
having sum(p.user_id = 1) > 0 and -- user 1 in conversation
sum(p.user_id in (4, 6)) > 0; -- user 4 and/or 6 in conversation

What I understand from your questions was you want to see users "4,6" involved in conversation with user_id = 1. to do so try following query.
select * from (SELECT conversations.id as conversation_id, participants.user_id as selectedUser, GROUP_CONCAT(participants.user_id) AS participants
FROM `conversations`
INNER JOIN `participants` ON `conversations`.`id` = `participants`.`conversation_id`
GROUP BY participants.conversation_id ) as derivedTable
where
selectedUser=1 and
(participants like '%4%' and participants like '%6%')
what above query does is. initially it will take all record from conversation and participants table and concat all participants agains user_id=1. then outer query checks are pretty clear to find user_id and participants have 4 and 6.

Related

List rows that have an ID in common in the same table with MySQL

I'm building an activities website and I want to show on user's profiles the common activities I'm going to with this other user.
So I have a table as follow :
Every time a user clicks "join" on an activity page, a new row is added to this table with :
the user_id who joined
the activity_id (event) attended
So on each user's profile, I want to list the different activities we have in common.
If the user's IDs are for example 1 and 10, then I can list the activities they go to with this query :
SELECT * FROM `activity_user` WHERE user_id IN(1, 10)
However, how to update this query to return only activities IDs they have in common?
It's a simple JOIN with the same table:
SELECT a1.activity_id
FROM activity_user a1
JOIN activity_user a2 ON a2.activity_id = a1.activity_id
WHERE a1.user_id = 1
AND a2.user_id = 10
Another way is to GROUP BY activity_id and only return activities, which both users have, by counting the rows per group:
SELECT activity_id
FROM activity_user
WHERE user_id IN(1, 10)
GROUP BY activity_id
HAVING COUNT(*) = 2
If the number of user is only limited to 2, this is quite simple using intersect clause -
SELECT activity_id
FROM `activity_user`
WHERE user_id = 1
INTERSECT
SELECT activity_id
FROM `activity_user`
WHERE user_id = 10
For two users you can join two SELECT against same table on activity_id
SELECT a.activity_id
FROM test a
JOIN (SELECT activity_idFROM test WHERE user_id = 10) b ON a.activity_id = b.activity_id
WHERE a.user_id = 1

Get table 1 record that is common to mutiple table 2 records when there's a many to many relationship between tables

I have three tables, chats, users and chat_user, where chat can have mutiple users and users can have multiple chats. I want to get the chat that is common to all the given user ids.
chats (id)
users (id)
chat_user (id, chat_id, user_id)
I want to get chat that belongs to user 1 and 5 or multiple user ids
Edit
I'm using Laravel framework, so it's better if there's a way to get the result through one of parent tables(users, chats).
But any help would be appreciated.
You may need to join the tables chats (the one that contains the informations you want) and the table chat_user (the one that contains the id of the chat and of the user) to apply where clause on the joined table.
In Laravel, I don't know.
SELECT c.*
FROM `chats` c
JOIN `chat_user` cu
ON c.id = cu.chat_id
WHERE cu.chat_id NOT IN (
SELECT cuu.chat_id
FROM chat_user cuu
WHERE cuu.user_id NOT IN (1, 5))
I am guessing that the userId will be an input parameter here? Try the query below:
SELECT
*
from
chats
WHERE
id in (
SELECT
chat_id
from
chat_user
WHERE
user_id = '1'
OR user_id = '5'
group by
chat_id
having
count(*) = 2
)
The count(*)=2 will ensure only those chats where both user 1 and 5 are present.

Two tables and join and left join together

I have a users table and user_followings table. The tables have the basic structure:
users: id, name, email
users_followings: following_user_id, follower_user_id
follower_user_id is someone who is following some other person.
following_user_id is someone who is being followed by some other
person
I want that one can click on a particular user to see all the information like who are following him/her and who are the people that he/she is follwing.
SELECT
users.id,
users.name,
users.email
from users
JOIN user_followings ON
user_followings.follower_user_id = users.id
WHERE user_followings.following_user_id = 1
This query basically joins two table and fetches desired result.
Now suppose a user named 'A' is logged in and he is looking at user X's profile. There are many people who have followed user X.
Let's say John, Mike, Rusev, Jack etc
How can write a query that tells whether logged in User 'A' is following John, Mike, Rusev, Jack etc or not along with the query that is above there.
So user A should be able to know whether he is following John, Mike, Rusev, Jack etc or not
My understanding is that OP wants to see what users are following the current user (A) that also follows the user A is viewing (X)
In my example A is id = 1 and X is id = 6
SELECT fu.id, fu.name, fu.email
FROM users u
JOIN users_followings f ON f.userId = u.id
JOIN users fu on fu.id = f.follower
WHERE f.userId = 1
AND f.follower IN (SELECT follower
FROM users_followings
WHERE userId = 6)
I changed follower_user_id to follower and following_user_id to userId to not confuse myself
Supposed the user with id=1 is viewing the details of the user with id=2 and you want to the user with id=1 to know if the followings or followers of user with id=2 are related with user with id=1 in any way. Try this:
SELECT C.*,
(SELECT 1 FROM user_followings D WHERE D.following_user_id=1 AND
C.id=D.follower_user_id LIMIT 1) flwx_viewing_user,
(SELECT 1 FROM user_followings E WHERE E.follower_user_id=1 AND
C.id=E.following_user_id LIMIT 1) viewing_user_flwx
FROM
(SELECT A.id, A.name, A.email, 'following' relation
FROM users
WHERE EXIST (SELECT 1
FROM user_followings B
WHERE B.following_user_id=2)
UNION ALL
SELECT A.id, A.name, A.email, 'followers' relation
FROM users
WHERE EXIST (SELECT 1
FROM user_followings B
WHERE B.follower_user_id=2)) C;
I'm not sure I get it right but given ID=1 for A and ID=5 for X.
This query returns for every user that follows X the info if it is followed by A
SELECT
*,
CASE WHEN exists(
SELECT *
FROM following AFOLLOW
WHERE AFOLLOW.follower_user_id = 1
AND XFOLLOWED.follower_user_id = AFOLLOW.following_user_id)
THEN 'FOLLOWING'
ELSE 'NOTFOLLOWING' END
FROM following XFOLLOWED
WHERE following_user_id = 5
AND follower_user_id <> 1;

How can I search through members that aren't friends of the current user in MySQL?

I have a members table and a member requests table. In the requests table are columns for author id and recipient id and also status. If the current user has a row with their ID as the author id and another member as the recipient id(or vice versa) and the status is 1, then the user is friends with that member. I would like to set up a search system that can be used to find members that the user isn't friends with by the name they type in. The query below is used to find the user's current friends by a name they type in. How can I search through members that the user isn't friends with?
SELECT
r.author_id, m.member_id, m.display_name
FROM member_requests AS r
LEFT JOIN members AS m ON m.member_id = r.author_id
WHERE r.recipient_id = 1
AND r.status = 1
AND m.display_name LIKE "John%"
UNION SELECT
r.recipient_id, m.member_id, m.display_name
FROM member_requests AS r
LEFT JOIN members AS m ON m.member_id = r.recipient_id
WHERE r.author_id = 1
AND r.status = 1
AND m.display_name LIKE "John%"
http://sqlfiddle.com/#!2/eb0d4d/3
This one is a lot easier than you think. Based off my answer from the last question, if you have a list of members someone IS friends with, you can search the members table for IDs that are not in that list.
Try this:
SELECT member_id
FROM members
WHERE member_id NOT IN(
SELECT recipient_id AS friends
FROM member_requests
WHERE author_id = 1 AND status = 1
UNION
SELECT author_id AS friends
FROM member_requests
WHERE recipient_id = 1 AND status = 1)
AND member_id != 1;
SQL Fiddle.

basic join on mysql

I am having a hard time understanding joins on mySQL, and I cannot find any similar example to work with.
Suppose I have two tables: users and users_info.
in users I have id, email and password fields while, in users_info I have all their information, like name, surname, street, etc.
so, if I am getting a user like this:
SELECT * FROM users WHERE id = 43
and their information like this:
SELECT * FROM users_info WHERE id = 43
I will basically get 2 results, and 2 tables.
I understand now that I need to use join so that they are all together, but I just can't figure out out.
Any help?
It seems like both tables users and user_info are related with each others by the column id therefore you need to join them using this column like this:
SELECT
u.id,
u.email,
u.password,
i.name,
i.surname,
i.street
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id;
This will only select the fields id, email, ... etc. However, if you want to select all the columns from both the tables use SELECT *:
SELECT *
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id;
If you want to input the id and get all of these data for a specific user, add a WHERE clause at the end of the query:
SELECT *
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id
WHERE u.id = 43;
For more information about JOIN kindly see the following:
Join (SQL)From Wikipedia.
Visual Representation of SQL Joins.
Another Visual Explanation of SQL Joins.
Here's an example
SELECT * FROM users u
INNER JOIN users_info i
ON u.id=i.id
this means, you are joining users table and users_info table
for example
users
id name
---- -------
1 abc
2 xyz
users_info
id email
--- ------
1 abc#aaa.com
2 xyz#aaa.com
the query will return
id name email
--- ----- -------
1 abc abc#aaa.com
2 xyz xyz#aaa.com
Here's a nice tutorial
You can also do:
SELECT users.*, users_info.*
FROM users, users_info
WHERE users.id = users_info.id AND users.id = 43;
This means:
"Get me all the columns from the users table, all the columns from the users_info table for the lines where the id column of users and the id column of users_info correspond to each other"