Mysql group concat on double join - mysql

I have a user table from which I want all values, so I have this query:
SELECT tbl_user.* FROM tbl_user
Now I want one additional column in this result which shows all roles this user has, (or nothing if there are no roles for the user). The role information comes from two additional tables.
The first table contains these two values: userid, roleid
The second table contains roleid and role_name.
So the group concat needs to get all role names based on the roleid's in table1.
I have tried several different ways to do this, but I don't succeed. Either I get only one result with several times the same rolename, or no result at all.
Thanks for your help
Michael

Update: added LEFT JOIN for users with no role.
SELECT
tbl_user.*,
GROUP_CONCAT(role_name) AS roles
FROM
tbl_user LEFT JOIN tbl_roles ON tbl_user.userid = tbl_roles.userid
JOIN tbl_rolenames ON tbl_roles.roleid = tbl_rolenames.roleid
GROUP BY tbl_user.userid
Note that MySQL will permit a GROUP BY on fewer columns than appear in the SELECT list in total, but in other RDBMS you would need to explicitly list out the columns in tbl_user and include them in the GROUP BY, or do an additional self join against tbl_user to get the remaining columns from that table.
Something like:
SELECT
urole.userid,
uall.username,
uall.name,
uall.othercols,
urole.roles
FROM
tbl_user uall JOIN (
SELECT
tbl_user.userid,
GROUP_CONCAT(role_name) AS roles
FROM
tbl_user LEFT JOIN tbl_roles ON tbl_user.userid = tbl_roles.roleid
JOIN tbl_rolenames ON tbl_roles.roleid = tbl_rolenames.roleid
GROUP BY tbl_user.userid
) urole ON uall.userid = urole.userid

Related

Querying with Many To Many in SQL

so I have two tables: "Group" and "Users" which have a many to many relationship. A group can have many users, and a user can have many groups. I need to be able to query all groups the user is in, and I also need to be able to have all of the other users that are in the group. Right now I am only able to query all the user's groups but in the group.users property it gives me back only one user.
You could try doing a left outer join from group to users and then doing another from users to group and union all to get all permutations or union to get distinct permutations.
Pseudo Code.
Select USERID, GroupID
FROM User
LEFT OUTER JOIN Group
ON Group.UserID = User.UserID
UNION --- Or UNION ALL If you wanted all relationships without removal of duplicates.
SELECT UserID, GroupID
FROM Group
LEFT OUTER JOIN User
ON User.GroupID = Group.GroupID

Retrieve a table that contain the same fields in a specific column

I have a table of Users that contain this columns: l_code, l_name, year_of_birth.
I need to return a table that contain all the pairs of users (different) that have the same year of birth.
The new table will contain: user1, user2, year_of_birth. How can i implement that with sql query?
Self join will do:
select t1.l_code, t1.l_name, t2.l_code, t2.l_name, t1.year_of_birth
from your_table t1
inner join your_table t2
on t1.year_of_birth = t2.year_of_birth
and t1.l_code <> t2.l_code;
You might want to keep the l_code column as there can be potentially many users with same name.
NOTE: It'll not produce those users which don't have any other user will the same year_of_birth, but you can fiddle with outer joins to achieve that.

mysql inner join interrogate 3 tables

I have a table in a MySQL DB, called ‘users’. The fields for users are : id, email, username, first_name, last_name. Another table in the same MySQL DB, called ‘premium_users’ , contains 2 fields : user_id, premium_service_id. A third table called ‘premium_services’ contains 2 fields : premium_service_id , premium_service_name.
I want to create an SQL query , to interrogate my db, so i can have a full list of what premium services has every premium user. How can i interrogate properly with inner join? I’ve try this :
select * from users inner join premium_users on users.id = premium_users.user_id inner join premium_services on premium_users.premium_service_id = premium_services.premium_service_id;
Since you say which service has every user, you'll need to use aggregation to determine this. Here's one way:
select user_id
from premium_users
group by user_id
having count(*) = (select count(*) from premium_services)
SQL Fiddle Demo
Depending on your data, you may need count(distinct premium_service_id) instead, but you should have constraints that don't allow duplicates in those table.
Rereading your question, I might have got this backwards. Looks like you want a list of premium services instead of users. Same concept applies:
select ps.premium_service_id
from premium_services ps
join premium_users pu on ps.premium_service_id = pu.premium_service_id
group by ps.premium_service_id
having count(distinct pu.user_id) = (select count(distinct user_Id) from premium_users)
More Fiddle

Combining RIGHT JOIN with COUNT

I'm trying to get a list of the number of entries in the changes_cc table by each user. Not all users have made entries into it, however for some reason it's returning "1" for each user that has 0 entries. I'm assuming that it's because it's counting the entries in the JOINed table. How can I make it so that it is "0" instead?
SELECT COUNT(*) as num, users.id, realname, username
FROM changes_cc
RIGHT JOIN users
ON changes_cc.user_id = users.id
GROUP BY users.id
I think this should work -- count a specific field in the changes_cc table vs counting *:
SELECT u.id, realname, username, COUNT(c.id) as num
FROM users u
LEFT JOIN changes_cc c
ON u.user_id = c.id
GROUP BY u.id
I prefer reading a LEFT JOIN over a RIGHT JOIN, but they are both OUTER JOINs and work the same.
You should not be using COUNT(*) (counts the record including null values) because it will normally give atleast 1 since it returns all records from the right table. If you specify the column name to be counted, it will gove you the result you want because COUNT only counts for NON_NULL value.
SELECT COUNT(changes_cc.user_id) as num,
users.id,
realname,
username
FROM changes_cc
RIGHT JOIN users
ON changes_cc.user_id = users.id
GROUP BY users.id
Instead of using count(*), use count(changes_cc.user_id).
The problem is that you are counting rows (with the *) rather than counting the non-NULL values in the "right-joined" table.

MySQL select rows that do not have matching column in other table

I can't seem to figure this out so far. I am trying to join two tables and only select the rows in table A that do not have a matching column in table B. For example, lets assume we have a users table and a sent table.
users table has the following columns: id, username
sent table has the following columns: id, username
I want to select all rows from users where username does not exist in sent table. So, if tom is in users and in sent he will not be selected. If he is in users but not in sent he will be selected. I tried this but it didn't work at all:
SELECT pooltest.name,senttest.sentname
FROM pooltest,senttest
WHERE pooltest.name != senttest.sentname
Typically, you would use NOT EXISTS for this type of query
SELECT p.Name
FROM pooltest p
WHERE NOT EXISTS (SELECT s.Name
FROM senttest s
WHERE s.Name = p.Name)
An alternative would be to use a LEFT OUTER JOIN and check for NULL
SELECT p.Name
FROM pooltest p
LEFT OUTER JOIN senttest s ON s.Name = p.Name
WHERE s.Name IS NULL
Note that the implicit join syntax you are using is considered obsolete and should be replaced with an explicit join.
Try this SQL:
SELECT users.username
FROM users
LEFT JOIN sent ON sent.username = users.username
WHERE sent.username IS NULL;
The better way in my opinion would be:
SELECT users.username
FROM users
LEFT JOIN sent ON sent.id = users.id
WHERE sent.id IS NULL;
As both the id fields, would be indexed (primary key I would have thought) so this query would be better optimised than the first one I suggested.
However you may find my first suggestion better for you, it depends on what your requirements are for your application.
May be this one can help you ....
I had also the same problem but Solved using this this query
INSERT INTO tbl1 (id,name) SELECT id,name from tbl2 where (name) not in(select name from tbl1);
hope this one will solve your problem