Fetch users which have only status = 1 - Mysql query on same column - mysql

I want a list of user_id which shouldn't have zero status.
Lets say, I have task table with user id, status. I'm trying to write a query to fetch user ids which have status = 1 only but not 2. As for below table, it should get me users id of tables with only status =1;
User table
id
etc
100
anything
200
anything
300
anything
Tasks table:
id
user_id
status
1
100
1
2
100
2
3
200
2
4
300
1
5
200
2
6
300
1
I have tried this query
SELECT user_id FROM tasks where status =2 and status != 1;
The above user id 100 has two tasks one with status 1 and other with status 2, I don't want that user.
The above user id 200 has two tasks but none of them has status 1, that is what i want.
The above user id 300 has both tasks with status 1, I don't want it too.
Status 1 means open. So I want a query which should get me users with zero open tasks only. If it has status 1 and 2 both, I don't want that.
I have tried multiple queries, but unable to find it.

Using sub queries with IN()/NOT IN() you can build a list of users having tasks in status 1/2 and filter your users based on those lists:
SELECT *
FROM users
WHERE
-- ensure the user has at least 1 task in status 1
id IN(
SELECT user_id
FROM tasks
WHERE status = 1
)
-- ensure the user has no task in status 2
AND id NOT IN(
SELECT user_id
FROM tasks
WHERE status = 2
)

I have task table with user id, status. I'm trying to write a query to fetch user ids which have status = 1 only but not 2
SELECT *
FROM users
WHERE EXISTS ( SELECT NULL
FROM tasks
WHERE users.id = tasks.user_id
AND statis IN (1) -- must have 1
)
AND NOT EXISTS ( SElECT NULL
FROM tasks
WHERE users.id = tasks.user_id
AND statis IN (2) -- must not have 2
)
To test multiple values put according list to according WHERE .. AND statis IN (..) list.

Related

How can I add multiple rows referring to another table?

Let's say I have two tables like below:
users table:
user_id
name
0
kevin
1
alice
2
jake
3
mike
permissions table:
user_id
permission
1
12
1
5
3
1
And let's say that I want to add permission 5 to every single user who doesn't already have it. What would be the best MySQL query for this?
Your question is not 100% clear whether you only need a query or you want to do inserts. Anyway, this query with NOT EXISTS can be used as base for all necessary actions:
SELECT user_id, 5 AS permission
FROM users u
WHERE NOT EXISTS
(SELECT 1 FROM permissions
WHERE permission = 5 AND user_id = u.user_id);
This will list all user id's that haven't yet a permission 5 and as second column, just 5 will be selected as permission.
Then this result can be used for whatever it should be used. For example to add this outcome in a query to the already present entries, UNION ALL can be used:
SELECT user_id, 5 AS permission
FROM users u
WHERE NOT EXISTS
(SELECT 1 FROM permissions
WHERE permission = 5 AND user_id = u.user_id)
UNION ALL
SELECT user_id, permission
FROM permissions
ORDER BY user_id, permission;
If - and I think this is your real question - the result of the NOT EXISTS query should be inserted into the permissions table, this insert command will do this:
INSERT INTO permissions
(SELECT user_id, 5
FROM users u
WHERE NOT EXISTS
(SELECT 1
FROM permissions
WHERE permission = 5 AND user_id = u.user_id));
You can try out these things here: db<>fiddle
Below query will look for missing user id in permissions and insert new records in permissions table with a default permission equal to 5.
INSERT INTO permissions
(
user_id,
permission
)
SELECT user_id,
5 AS permission
FROM users
WHERE user_id NOT IN
(
SELECT user_id
FROM permissions)
)
Sample result:
user_id
permission
1
12
1
5
3
1
0
5
2
5

Get Last row in each group and order whole array by ID(pk) DESC and join with other Table

I want the last row in each and every group(Group By user_id).
Structure of Table is like follows:
Table: user_messages
id(PK) | user_id(FK) | read_admin_status | created_at
1 5 0 date
2 5 0 date
3 5 0 date
4 5 1 date
5 6 1 date
6 6 1 date
7 7 0 date
8 7 0 date
Table: users
id | username
Now I want username from users tables and I want other details from user_messages.
Now I want data of user_id 5 and want it's last row only.
likewise for other groups I want last row of each group and from users table I want username by joining the tables.
Please help me out with this if you can. Thank you.
You might try something like this:
SELECT user_messages.id, users.username
FROM (
SELECT MAX(id) AS max_id
FROM user_messages
GROUP BY user_id
) AS ids
INNER JOIN user_messages ON ids.max_id = user_messages.id
INNER JOIN users ON user_messages.user_id = users.id
This query will choose the largest message ID in each user's group of messages, which is the same as getting the last ID when ordering by ID, and then use the associated user ID to get the username. I only selected the message ID and username, but you could get whatever information you wanted out of those tables.

Mysql Group by/Order by private messages list

Table structure
Id User_From User_To Time_sent Message Message_read
1 1 2 ~TimeLast ~Message 0
2 3 2 ~Time ... 0
3 3 2 ~TimeLast ... 0
How would I create a query that filters out all the unread messages but only shows the last one of them if more than 1 unread mes are in the table?
So Id get this as a result
Id User_From User_To Time_sent Message Mesage_read
1 1 2 LastTime ~~ 0
3 3 2 LastTime ~~ 0
Edit : this worked fine
select p.id,user_from,username,message,time_sent,message_read
from private_messages p join users u on p.user_from = u.id where p.id in (select max(id) as id from private_messages where user_to = :u1 group by user_from
So your result should only always give back one message? And this one message should be the last one sent? then this query would work
SELECT * FROM table WHERE Message_read 0
ORDER BY Time_sent LIMIT 1
it is simple using Mysql LIMIT, "Mysql Limit" can define how many results you will get, for example if you use "LIMIT 1" in your mysql query then you will get only 1 result.
SELECT * FROM table_name WHERE Message_read=0
ORDER BY Time_sent LIMIT 1
This should only return 1 result from table where Message_read=0 and that is latest in your table.

MySQL select rand and exclude users with condition

I need to select random user_id from "user" table, and completely exclude any user_id if current user have any "ongoing" battles with him battles.status
Query:
SELECT user.id
FROM user
LEFT JOIN battles b ON b.uid = user.id AND b.status <> 'ongoing'
WHERE user.id <> 1
ORDER BY RAND( )
LIMIT 1
But the query is not sufficient, because a user can have multiple battles with specific other users, one of them "ongoing" and the others "finished",
My query should select users from the "finished" row.
Tables structure:
user table:
id name
1 John
2 Sarah
3 Jack
4 Andy
5 Rio
battles table:
id uid uid2 status
1 1 2 finished
2 1 2 ongoing
3 2 3 ongoing
4 1 4 finished
5 3 5 finished
If "my" id = "1",
I want to completely exclude any user I have ongoing battle with him, like "2" in the above case and accept all other ids (i.e.3,4 and 5)
You probably want something along the lines of this:
SELECT foe.*
-- Select yourself and join all other users to find potential foes
FROM `user` AS me
INNER JOIN `user` AS foe
ON (me.id <> foe.id)
-- Here we select the active user
WHERE me.`id` = 1
-- Now we exclude foes we have ongoing battles with
-- (your id could be in either uid or uid2)
AND foe.`id` NOT IN (
SELECT `uid` FROM `battles`
WHERE `uid2` = me.`id` AND `status` = 'ongoing'
UNION ALL
SELECT `uid2` FROM `battles`
WHERE `uid` = me.`id` AND `status` = 'ongoing'
);
This will return a list of users which you do not currently have ongoing battles with. You can customise this to return just one of them using LIMIT and random ordering like in your example.

common values b/w fields

This table lists user and item id's
user_id item_id
1 1
1 2
1 3
2 1
2 3
3 1
3 4
3 3
How can I run a query on this table to list all the items that are common between given users.
My guess is, this will need a self join, but I'm not sure.
i am trying this quering but it's returning an error
SELECT *
FROM recs 1
JOIN recs 2 ON 2.user_id='2' AND 2.item_id=1.item_id
WHERE 1.user_id='1'
Try using alias names that start in a letter:
SELECT *
FROM recs r1
JOIN recs r2 ON r2.user_id='2' AND r2.item_id=r1.item_id
WHERE r1.user_id='1'
This returns
user_id item_id
------- -------
1 1
1 3
for your data. Demo on sqlfiddle.
Note: I kept single quotes in the query, because I assume that both IDs in your table are of character type. If that is not the case, remove single quotes around user ID values '1' and '2'.
I want it for n number of users ... a I want the query to return all item_id's that are common among the users
SELECT DISTINCT(r1.item_id)
FROM recs r1
WHERE EXISTS (
SELECT *
FROM recs r2
WHERE r2.item_id=r1.item_id
AND r1.user_id <> r2.user_id
)
Demo #2.