Adding a row if it does not exist in a MySQL table - mysql

Inside a table there are 2 columns: userid and roleid. Every user should atleast have roleid 4 . There are currently around 10.000 records, but somehow a small amount of users do not have this role.
Visual example:
userid | roleid
1 1
1 4
2 1
2 4
3 1 <---------- userid 3 misses roleid 4!
4 1
4 4
Is it possible to execute a query and add a row with the userid and roleid when that combination does not exist?

Yes.
insert into userRoles(userid, roleid)
select userid, 4
from userRoles
group by userid
having sum(roleid = 4) = 0;
The sum(role = 4) in the having clause counts the number of rows for each user that have 4. The = 0 says there are none.
Note: This gives all users in this table a role id of 4. There may be users with no roles at all.
If you want them, then use the users table:
insert into userRoles(userid, roleid)
select u.userid, 4
from users u
where not exists (select 1 from userRoles ur where ur.userid = u.userid);

You should search for user that have not 4 in roleID
insert into yourTable ( userId, roledid)
select userid, 4
from yourTable
where roleid <>4

Related

How to find the dependency that brought another dependency in MySQL or Redshift

There is two tables:
dependency_permission table:
id
dependency_permission_id
2
1
4
2
user_permission table:
id
user_id
permission_id
1
11111
1
2
22222
4
3
22222
2
4
11111
2
5
33333
2
I want to write a query that finds all user_id's which have permissions depend on another permission the user doesn't have.
from the above data, users (22222 and 33333) should be returned, they don't have permission 1 which 2 depends on.
You may left join the 'user_permission' table with the 'dependency_permission' to get the 'dependency_permission_id' for each user 'permission_id', then use NOT EXISTS operator to check the existence of 'dependency_permission_id' for each user 'permission_id'.
with user_dependency_permission as
(
select U.user_id, U.permission_id, D.dependency_permission_id
from user_permission U left join dependency_permission D
on U.permission_id = D.id
)
select user_id, permission_id /* if you want to select only user_ids use distinct user_id*/
from user_dependency_permission T
where not exists(
select 1 from user_dependency_permission D
where T.user_id=D.user_id and
D.permission_id=T.dependency_permission_id
)
and T.dependency_permission_id is not null
See a demo on MySQL.

Show repeated values on a simple MySQL query

Having this two users:
id = 143 user = User 1
---- id = 91 user = User 2
and this simple query:
SELECT name FROM users where id IN (143,143,91);
It two results:
User 1
User 2
Is there any way to return the repeated values as well? My desired output would be:
User 1
User 1
User 2
I think what you want is UNION ALL:
SELECT name FROM users where id = 143
UNION ALL
SELECT name FROM users where id = 143
UNION ALL
SELECT name FROM users where id = 91
One simple query will do not return the same 143 twice.
As far as I know, creating another table inserting all the ID you want to extract:
CREATE TABLE TUSERS (ID INT, NAME VARCHAR(20));
INSERT INTO TUSERS VALUES (91, 'User2');
INSERT INTO TUSERS VALUES (143, 'User1');
CREATE TABLE TMP01 (ID INT);
INSERT INTO TMP01 VALUES(143);
INSERT INTO TMP01 VALUES(143);
INSERT INTO TMP01 VALUES(91);
SELECT A.*
FROM TUSERS A
RIGHT JOIN TMP01 B ON A.ID=B.ID;
Output:
ID NAME
143 User1
143 User1
91 User2
The IN list is simply used for filtering existing rows. If you want all values, then an outer join is recommended. You can produce the IN list on the fly:
select u.name
from (select 143 as id union all
select 143 union all
select 91
) ids left join
users u
on u.id = i.id;

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.

Getting Follower and FollwedBy Users from Table in one list

I have a Table that tracks followers
FollowerUserId, FollowingUserId
1 2
2 1
3 1
4 1
1 5
I want to get all user that given Id follows and is followed by or Both.
for example for UserId 1,I want result to be: (FG: Following, FD: Followed, B: Both ways)
2,B
5,FG
3,FD
4,FD
i can easily get FG and FD by doing union
Select FollowerUserId, 'FD' From Table Where FollowingUserId =1
Union
Select FollowingUserId, 'FG' From Table Where FollowerUserId =1;
with above i get user 2 as
2,FG
2,FD
from above but I really need 2,B without UserId 2 duplicated.
How can this be done efficiently?
You can use aggregation on your basic query:
SELECT UserId,
(CASE WHEN COUNT(DISTINCT which) = 1 THEN MIN(which)
ELSE 'B'
END)
FROM (Select FollowerUserId as UserId, 'FD' as which From Table Where FollowingUserId = 1
Union ALL
Select FollowingUserId, 'FG' From Table Where FollowerUserId = 1
) f
GROUP BY UserId;

select rows in mysql having another column with same value

I have a table that manage conversations of a chat between users, the structure is the following.
id | user_id | conversation_id
let's say that on the conversation with ID 1 there are 3 people to chat and the conversation with ID 2, 2 people as well
Conversations_users table will look like this
id | user_id | conversation_id
1 1 1
2 2 1
3 4 1
4 3 2
5 4 2
Now having only the id of the users 3 and 4 and Not Conversation ID I would like select the conversation that belongs to that users so a verbal query should be:
Select from conversations_users, where in user_id = 3 and 4 and conversation_id is equals to conversation id of user 3 and 4
how can I build this "verbal query" in Mysql?
to get all the users in the conversations that user 3 and 4 are part of you could use this:
select distinct(user_id) from conversation_table where conversation_id in (select distinct(conversation_id) from conversation_table where user_id in (3,4));
it won't be very fast though
to get their actual conversations, I'm assuming you have a different table with the text in it:
you probably want something like this
select distinct(u.user_id), c.text from conversation_table u left join conversations c on c.id=u.conversation_id where u.conversation_id in (select distinct(conversation_id) from conversation_table where user_id in (3,4));
here is an sqlfiddle
Here is one method:
select uc.conversation_id
from UserConversions uc
where uc.user_id in (3, 4)
group by uc.conversation_id
having count(*) = 2;
If the table could have duplicates, you'll want: having count(distinct user_id) = 2.
EDIT:
If you want a specific list, just move the where condition to the having clause:
select cu.conversation_id
from conversations_users cu
group by cu.conversation_id
having sum(cu.user_id in (3, 4)) = 2 and
sum(cu.user_id not in (3, 4)) = 0;
I assume you have another table called "conversations" which holds the data you really want.
SELECT *
FROM conversations, conversations_users
WHERE conversations_users.user_id in (3,4)
AND conversations.id = conversations_users.conversation_id