SQL query to match table with multiple rows from another - mysql

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

Related

SQL - Hard time building a "complex" request

I've got three tables :
conversations (contains private conversations)
conversations-members - structure : convId | userId (contains all ids of members participating to a conversation so multiple people can talk together. One user participating to a conversation equals one row)
users (users table, classic)
What I am trying to do is :
Users have friends. So, the user browsing my application can open a conversation from his friends' ids.
So, first, I want to look up in conversations-members if there is an existing conversation ONLY between user's Id and his friend's Id and then, pick up the conversation id in conversations table that conversations-members gave me.
Is it possible to do this in one request? If I have to do two requests, I don't even know how to build the first one (find the rows that contain user's Id and friend's Id that have conversation Id in common).
My first idea was to make a single conversations table which would also contain member's Id in the form of a string like "55,105,85,22" and then parse it to get an array, but I think the way I want to do it gives me more options and could be simpler if I manage to handle the SQL requests I need.
To find conversations involving just two particular users, you can do something like this.
SELECT convId, COUNT(*)
FROM `conversations-members`
WHERE userId IN (FIRST_USER, SECOND_USER)
GROUP BY convId
HAVING COUNT(*) = 2
The HAVING line filters out any conversation with any users besides the two you want.
You can use that as a subquery:
SELECT whatever
FROM conversations
WHERE convId IN (
SELECT convId
FROM `conversations-members`
WHERE userId IN (FIRST_USER, SECOND_USER)
GROUP BY convId
HAVING COUNT(*) = 2
)
If you wanted conversations with your two users and any other users, you could change the subquery to HAVING COUNT(*) >= 2.
Pro tip: SQL thinks hyphens - mean subtraction. Avoid them in column and table names.
It's not recommended to use a column with multiple values.
When you have a relation 1-N, normally you need to use a table with two keys, for example, ConvID - UserID. Your index are created by these two columns, for don't allow to generate a duplicate (an UserID two times on the same ConvID, for example).
But, in response to your question, yes, it's possible to do that search. You need to search for an entry on your SQL table where two different IDs are on the same line. You can do it with LIKE clause, but it's not a good option (I think it's the worst possible WHERE clause).
The syntax will be as follows:
SELECT convId FROM conversations-members WHERE userId LIKE '%id1%' AND userId LIKE '%id2%'
For some additional recommendation, if your conversations are always a pair of people, use two new fields on your "conversations" table. If your conversation can have from one to N members, use the "conversations-members" as suggested at the start of the answer.

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

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.

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

Finding all polls that a specific user hasn't voted on yet

I have a website that displays poll after poll to a register user, and stores his vote in a table.
A simple structure of the database would be as follows (there are much more fields, but they don't contribute much to the question, so I removed them):
Polls(pollId)
Votes(pollId, userId, vote)
Now I want to run a MySql query to select all polls within the 'Polls' table, except for the polls that the current user had already voted on (which could be determined from the 'Votes' table)
Is it possible to make that using a MySql select statement alone, or will I have to select all polls first, and use some Php logic to filter out the ones already voted on by the user?
Thanks in advance!
SELECT *
FROM Pools
WHERE id NOT IN (
SELECT poolId
FROM Votes
WHERE userId = 142
)
Try something like this:
select p.pollid from polls p where p.pollid not in (select v.pollid from votes v where userId = {USERID})