SQL INSERT INTO two tables from one table - mysql

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

Related

Finding a list of mutual followers in mysql

I'm working on a sql query which requires me to generate a list of mutual followers (e.g. A follows B and B follows A)
Our table consists of the FriendshipID, FollowerUserID, FollowingUserID as shown below. Note that FollowerUserID folllows FollowingUserID enter image description here
I have tried creating a view table using the code below:
Create view MutualFriends AS
(select distinct a.FollowerUserID, a.FollowingUserID
from friendship as a, friendship as b
where a.FollowerUserID = b.FollowingUserID and a.FollowingUserID = b.FollowerUserID);
However, it returns a repeated view table, e.g. 1 follows 3 is repeated as 3 follow 1.
enter image description here
How can we remove the repeated rows in view?
Or are there any other ways to generate the results (without repeating)
Here is one way to do this, using a LEAST/GREATEST trick:
SELECT
LEAST(FollowerUserID, FollowingUserID) AS friend1,
GREATEST(FollowerUserID, FollowingUserID) AS friend2
FROM (SELECT DISTINCT FollowerUserID, FollowingUserID FROM friendship) t
GROUP BY
friend1,
friend2
HAVING
COUNT(*) = 2;
The subquery aliased as t first removes all duplicate follower/following pairs from the original friendship table. This may be necessary if a given one way relationship could appear more than once in the table, e.g. 1 -> 2 appears twice for some reason.
Then, we aggregate by the least of the follower/following and the greatest of the same pair. If we find that there are two such records, then it implies that the follower and following are mutual.
Just agree with solution from #Tim, but I think we don't need to use subquery at "FROM" step (select distinct from friendship....)
select
least(FollowerUserID, FollowingUserID) as u1,
greatest(FollowerUserID, FollowingUserID) as u2
from friendship
group by u1,u2
having count(*) = 2

SQL Friends List Query

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

Randomize a winner pair from the subscriptions

I have a project, where customer needs a winnner pair for events. The users of this site can "like" other user's (just like on FB), they subscribe to a particular post, and the script will generate a winner pair from the subscribers.
So I need a SQL query to randomize a winner pair from the list of pairs, where the users liked each other, and subscribed to a particular post.
How do i do that ?
I cant write a query that, because i got unexpected results.
I have 3 tables : events, likes, subs (and users ofc)
events table : event_id, event_name
subs table: sub_id, event_id, uid
likes table: liker, liked (the two uid from the users table)
Now I can make pairs from the likes table (i self-joined the table where liker = liked AND liked = liker) and randomized, but how can I join the subs and the events tables to the likes table to achieve that a randomized pair will be a subscribed users for a particular event too ?
My current query looks like this :
SELECT L.liked AS T1, L.liker AS T2
FROM likes AS L, likes AS K
WHERE L.liked = K.liker
AND L.liker = K.liked
ORDER BY rand( )
LIMIT 0 , 1
I googled everything about joins for one week, but i cant achieve that.

SQL query to match table with multiple rows from another

Apologies for the poorly worded question.
I have two tables, called conversations and conversation_users. Each conversation can have multiple users attached to it. The fields are as follows:
conversations
conv_id
conv_author_id
conv_date
conversation_users
cu_id
cu_conv_id
cu_user_id
Now, to avoid duplication of conversations with the same users. I want to check whether a conversation already exists with users with ID, say 12 and 25. If one exists, I wish to obtain the ID of that conversation.
How do I go about structuring a query to do this?
I want to check whether a conversation already exists with users with
ID, say 12 and 25.
You can use EXISTS:
SELECT CASE WHEN EXISTS
(
SELECT 1 FROM conversation_users cu
WHERE cu.cu_conv_id = c.conv_id
AND cu.cu_user_id IN (12, 25)
) THEN 'Yes, these users are in this conversation'
ELSE 'This conversation is between different users' END AS Result
FROM conversations c

How do I select a record from one table in a mySQL database, based on the existence of data in a second?

Please forgive my ignorance here. SQL is decidedly one of the biggest "gaps" in my education that I'm working on correcting, come October. Here's the scenario:
I have two tables in a DB that I need to access certain data from. One is users, and the other is conversation_log. The basic structure is outlined below:
users:
id (INT)
name (TXT)
conversation_log
userid (INT) // same value as id in users - actually the only field in this table I want to check
input (TXT)
response (TXT)
(note that I'm only listing the structure for the fields that are {or could be} relevant to the current challenge)
What I want to do is return a list of names from the users table that have at least one record in the conversation_log table. Currently, I'm doing this with two separate SQL statements, with the one that checks for records in conversation_log being called hundreds, if not thousands of times, once for each userid, just to see if records exist for that id.
Currently, the two SQL statements are as follows:
select id from users where 1; (gets the list of userid values for the next query)
select id from conversation_log where userid = $userId limit 1; (checks for existing records)
Right now I have 4,000+ users listed in the users table. I'm sure that you can imagine just how long this method takes. I know there's an easier, more efficient way to do this, but being self-taught, this is something that I have yet to learn. Any help would be greatly appreciated.
You have to do what is called a 'Join'. This, um, joins the rows of two tables together based on values they have in common.
See if this makes sense to you:
SELECT DISTINCT users.name
FROM users JOIN conversation_log ON users.id = converation_log.userid
Now JOIN by itself is an "inner join", which means that it will only return rows that both tables have in common. In other words, if a specific conversation_log.userid doesn't exist, it won't return any part of the row, user or conversation log, for that userid.
Also, +1 for having a clearly worded question : )
EDIT: I added a "DISTINCT", which means to filter out all of the duplicates. If a user appeared in more than one conversation_log row, and you didn't have DISTINCT, you would get the user's name more than once. This is because JOIN does a cartesian product, or does every possible combination of rows from each table that match your JOIN ON criteria.
Something like this:
SELECT *
FROM users
WHERE EXISTS (
SELECT *
FROM conversation_log
WHERE users.id = conversation_log.userid
)
In plain English: select every row from users, such that there is at least one row from conversation_log with the matching userid.
What you need to read is JOIN syntax.
SELECT count(*), users.name
FROM users left join conversion_log on users.id = conversation_log.userid
Group by users.name
You could add at the end if you wanted
HAVING count(*) > 0