Mysql count how many answers are correct - mysql

I have table user_answers :
id | quiz_id | user_id | question_id | choosen_answer_id |
1 | 1 | 2 | 1 | 5 |
2 | 1 | 2 | 2 | 6 |
3 | 1 | 2 | 3 | 7 |
4 | 1 | 3 | 1 | 5 |
5 | 1 | 3 | 2 | 8 |
6 | 1 | 3 | 3 | 9 |
I want to cont how many correct answers (same choosen_answer_id for same question_id ) has user with user_id = 3 compared with user_id = 2 on same quiz_id
In this example I should receive 1 because user with user_id = 3 answered correct only on question with question_id=1 (for user_id = 2, question_id = 1 choosen_answer_id = 5 and for user_id = 3, question_id = 1 choosen_answer_id = 5`).
Thanks

I understand that you are willing to count for how many questions both users have given the same answer. You could self-join the table as follows :
SELECT COUNT(*) AS number_of_identical_answers
FROM user_answers ua2
INNER JOIN user_answers ua3
ON ua3.user_id = 3
AND ua3.quiz_id = ua2.quiz_id
AND ua3.question_id = ua2.question_id
AND ua3.choosen_answer_id = ua2.choosen_answer_id
WHERE ua2.user_id = 2
If you want to display the joined records instead of counting them, you can change COUNT(*) to a list of columns from tables ua2 (answers of user 2) and ua3 (answers of user 3).

select user_id, count(*)
from table1 t1
join (select *from table1 where user_id = 2) t2
on t2.question_id = t1.question_id
where t2.choosen_answer_id = t1.choosen_answer_id
group by t1.user_id

Related

Select records in one table and specific matching records from the other

I have three tables, two of which are relevant for this question. Users, Things, User_to_thing
Users
ID | Name | Active
-------------------
1 | Joe | 1
2 | Jack | 1
3 | Tom | 1
4 | Harry | 0
5 | Stan | 1
6 | Bob | 1
User_to_thing
Thing ID | User ID | Status
---------------------------
3 | 1 | 1
3 | 2 | 2
3 | 5 | 1
4 | 1 | 3
4 | 2 | 2
I'm trying to create a query where I can select all the active users in the users table and have a column where I can see the status for "thing 3" from the User_to_thing table while also sorting results so that the nulls come at the end. So the result would be something like:
User ID | Status
----------------
1 | 1
2 | 2
5 | 1
3 | NULL
6 | NULL
What I have so far for a query is the following:
SELECT u1.id, u1.name, user_to_thing.status
FROM users u1
LEFT JOIN user_to_thing ON u1.id = user_to_thing.user_id
WHERE u1.active = 1
OR user_to_thing.event_id = 62
ORDER BY (CASE WHEN user_to_thing.status = 1 THEN 1
WHEN user_to_thing.status = 2 THEN 2
ELSE 3 END)
What I'm getting as a result is the following:
User ID | Status | Thing ID
---------------------------
1 | 1 | 3
1 | 3 | 4
2 | 2 | 3
2 | 2 | 4
5 | 1 | 3
3 | NULL | NULL
6 | NULL | NULL
I'm not sure how to limit it to just thing #3 while also getting a list of all active users. Any guidance would be appreciated.
It looks like the following should work for you, grouping to remove duplicates and ordering based on null
select u.Id as UserId, t.status
from users u
left join User_to_thing t on t.UserID = u.id
where u.active = 1
group by u.Id, t.Status
order by case when status is null then 1 else 0 end, u.Id
Based on your revised data, you can amend slightly
select u.Id UserId, Min(t.status) Status
from users u
left join User_to_thing t on t.UserID=u.id
where u.active=1
group by u.Id
order by case when Min(t.status) is null then 1 else 0 end, u.Id

How to create right query?

I'm trying write a query:
SELECT id FROM users WHERE status = 3
But if this sample returns an empty response, then I need instead to select the id where status = 4, and if it returns empty again, where status = 5.
How can I write a single query to solve this?
I think you simply want:
SELECT id
FROM users
WHERE status >= 3
ORDER BY status asc
LIMIT 1;
If you want multiple users:
SELECT u.id
FROM users u
WHERE u.status = (SELECT MIN(u2.status)
FROM users u2
WHERE u2.status >= 3
);
If you have a fixed list you want to test, you can also use:
select u.id
from users u
where u.status = 3
union all
select u.id
from users u
where u.status = 4 and
not exists (select 1 from users u2 where u2.status in (3))
union all
select u.id
from users u
where u.status = 5 and
not exists (select 1 from users u2 where u2.status in (3, 4));
You can use OR condition or use IN operator
SELECT id FROM users WHERE status = 3 or status = 3 or status = 5
or
SELECT id FROM users WHERE status IN (3,4,5)
I will use the case statement in the where clause:
select id
from users
where status = case when status = 3 and id is null then 4
when status = 4 and id is null then 5
else 3
end
Let me know if you have any question.
Assuming that your table look like this:
+----+--------+
| id | status |
+----+--------+
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 3 | 3 |
| 3 | 4 |
| 4 | 4 |
| 4 | 5 |
| 5 | 5 |
+----+--------+
And based on your condition where you want to see the lowest status first for each id, you can use MIN() operator.
So, from your original query:
SELECT id,MIN(status) FROM users GROUP BY id;
Then you'll get a result like this:
+----+-------------+
| id | MIN(status) |
+----+-------------+
| 1 | 3 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
+----+-------------+

How to find if two person following each other

This is my table following now i want to find the list of follower of user 1 that are also followed by user 1
id | user | follower
-----------------------
1 | 1 | 2
2 | 2 | 1
3 | 1 | 3
4 | 3 | 1
For example i want to find the list of my followers who are also following me
With EXISTS:
select t.follower from tablename t
where
t.user = 1
and exists (
select 1 from tablename
where user = t.follower and follower = t.user
)
See the demo.
Results
| follower |
| -------- |
| 2 |
| 3 |
You could self-join the table:
SELECT f1.user
FROM followers f1
JOIN followers f2 ON f1.user = f2.follower AND f1.follower = f2.user
WHERE f1.follower = 1 -- For a specific user

mysql LEFT JOIN main table and two additional tables with max value from each

So i have three tables:
Users
+-------+-----+----+
| id | val1|val2|
+-------+-----+----+
| 1 | 1 |3 |
| 2 | 2 |5 |
| 3 | 4 |7 |
+-------+-----+----+
UsersData
+----+--------------+------------+-----|
| id | users_id | created_at | gold|
+----+--------------+------------+-----|
| 9 | 1 |121454561212| 14 |
| 10| 1 |131454561212| 2 |
| 11| 2 |111454561212| 99 |
+----+--------------+------------+-----+
Extra
+----+------------+-----|
| id | users_id | val4|
+----+------------+-----|
| 1 | 1 | 5 |
| 2 | 1 | 6 |
| 3 | 1 | 7 |
+----+------------+-----+
So what i wish to achieve(in a single query) is to get a single row result for user with id = 1, that holds:
everything from Users Table
gold value of the most recent entry for that user (users_id = 1, created_at = MAX)
biggest val4 from the Extra table, where users_id = 1
So the result row would look like this:
+-------+-----+----+-----+----+
| id | val1|val2|gold |val4|
+-------+-----+----+-----+----|
| 1 | 1 |3 | 2 | 7 |
------------------------------+
I can get The first part done with
SELECT Users.id, Users.val1, Users.val2, UsersData.gold
FROM UsersData
LEFT JOIN Users ON UsersData.users_id = Users.id
WHERE Users.id = 1
ORDER BY UsersData.created_at DESC
LIMIT 1
and the second part with
SELECT MAX(Distances.distance) AS maxdistance FROM Distances WHERE Distances.users_id = 1
But i can't combine them no matter how i try... I would really like to have this done in single query, obviously i can do it with multiple - but i believe it is just my lack of mysql skills that is the issue here.
Thanks!
Just use subquery:
SELECT Users.id, Users.val1, Users.val2, UsersData.gold,
(SELECT MAX(Distances.distance) FROM Distances WHERE Distances.users_id = Users.id) AS maxdistance
FROM UsersData
RIGHT JOIN Users ON UsersData.users_id = Users.id
WHERE Users.id = 1
ORDER BY UsersData.created_at DESC
LIMIT 1
This is subquery connected by Users.id:
SELECT MAX(Distances.distance) FROM Distances WHERE Distances.users_id = Users.id) AS maxdistance
I would use subqueries like this:
select u.*,
(select ud.gold
from userdata ud
where ud.users_id = u.id
order by ud.created_at desc
limit 1
) as most_recent_gold,
(select max(e.val4)
from extra e
where e.users_id = u.id
) as max_val4
from users u
where u.id = 1 ;

Advance select query in mysql

I have a table called 'connections' with these fields:
entry_id
user_id
connector_id
cat_id
Lets put some rows
| entry_id | user_id | connector_id |cat_id |
|:---------|---------|:------------:|:------------:|
| 1 | 11| 33 | 1
| 2 | 13| 11 | 2
| 3 | 9| 11 | 4
| 4 | 11| 33 | 6
| 5 | 33| 11 | 11
| 6 | 9| 11 | 8
Pseudocode
(using connection between id = 11 and oid = 9)
Select cat_id FROM connections c
if cat_id is between 1 and 5
where c.connector_id = id OR c.user_id = id
AND c.connector_id = oid OR c.user_id = oid
else if cat_id is greater than 5
where oid = user_id and id = connector_id
In english;
If the cat_id is between 1 and 5, it should select cat_ids from where oid and id are both in connector_id or user_id, it doesn't matter which order as long as they are in one or the other, but if the cat_id is greater than 5, it should only select cat_ids where oid is the user_id and id is the connector_id.
Result (for connection between id = 11 and oid = 9)
| cat_id |
|:-----------|
| 4 |
| 8 |
One more example:
Result (for connection between id = 33 and oid = 11 )
| cat_id |
|:-----------|
| 1 |
| 6 |
Please ask if they're parts that are not clear.
You should be able to accomplish this by just following your if statements logically. Something like:
Select cat_id FROM connections c
where
(id between 1 and 5 AND (c.connector_id = id OR c.user_id = id)
AND (c.connector_id = oid OR c.user_id = oid))
OR id > 5 AND (oid = user_id and id = connector_id)
Note: in agreement with some of the comments - ensure this is what you need to be doing. I made some assumptions about how you intended your logic to be from the pseudo-code, these may be wrong - so please think about it before just copying and pasting. This specifically applies to how you structured your OR / AND in the where clause.