group_concat multiple rows where given condition - sql

I have 3 tables (User, User_usergroups , usergroup). I would like to get a list of user who has usergroup equal to "member" and other groups (group_concat) belonging to this user. How do I do that?
I got the first part of the query, but I could not get other groups, aggregated groups of this user (I like to use group_concat to concatenate other groups in one field.
SELECT user.userId, (group_concat(group_.name)???)
FROM User_ user join Users_UserGroups userGroups
on user.userId= userGroups.userId
join UserGroup group_ on userGroups.userGroupId = group_.userGroupId
WHERE group_.name="member";
Assume that is the 3 tables
The outcome will be
Many thanks for your great help.

It looks like my query is so complex and it has down vote from the administrator or someone. I wish whoever did this could add their comment to my query so that, in the future, I will know what I need to do to clarify my question to the community or make my question better. Here is the answer to my question.
First retrieve the list of userId.
Then join this "member" table with other tables to find the result from the list of retrieved ID (step 1).
As we aggregate the name of the groups, we need to use groupby.
Keywords to resolve this problem is to use an alias for subquery or nested SQL
select member.userid, member.screenName, group_concat(member.name)
from (SELECT User_.userid userid, User_.screenName screenName , UserGroup.name name
FROM UserGroup
JOIN Users_UserGroups
ON UserGroup.userGroupId = Users_UserGroups.usergroupid
JOIN User_
on Users_UserGroups.userId = User_.userId
WHERE UserGroup.name = "member")member
JOIN Users_UserGroups
ON member.userid = Users_UserGroups.userId
JOIN UserGroup
on UserGroup.userGroupId=Users_UserGroups.userGroupId
GROUP BY member.userid;

Related

SQL query to exclude records that are part of a group

I can't believe this hasn't been answered elsewhere, but I don't seem to know the right words to convey what I'm trying to do. I'm using Ruby/Rails and PostgreSQL.
I have a bunch of Users in the DB that I'm trying to add to a Group based on a name search. I need to return Users that do not belong to a particular Group, but there is a join table as well (UserGroups, with the appropriate FKs).
Is there a simple way to use this configuration to perform this query without having to result to grabbing all the Users from which belong to the group and doing something like .where.not(id: users_in_group.pluck(:id)) (these groups can be pretty huge, so I don't want to send that query to the DB on a text search as the user types).
I need to return Users that do not belong to a particular Group
SELECT *
FROM users u
WHERE username ~ 'some pattern' -- ?
AND NOT EXISTS (
SELECT FROM user_groups ug
WHERE ug.group_id = 123 -- your group_id to exclude here
AND ug.user_id = u.id
);
See:
Select rows which are not present in other table

Relationships query PostgresSQL, Follow/Unfollow functionality with PostgresSQL

I have two tables, Users and Relationships tables. Users table has following columns:
id, name,password,username,email,avatar,followersCount,followingCount,tweetCount.
And the Relationships table has the following columns:
id, followingId, followerId
How should I go about creating a SQL query to extract a user with a specific Id and find id's from Relationships that user is following? So in other words find people that user follows
I've come this far so long
SELECT *
FROM public."Users" JOIN
public."Relationships"
ON (public."Users".id = public."Relationships".id)
If I understand correctly, you want:
SELECT u.*
FROM public."Relationships" r JOIN
public."Users" u
ON u.id = r.followerId
WHERE r.followingId = ?;
? is a parameter placeholder for the user you care about. This returns all the followers of that user.
Do you mean this query
SELECT public."Users".*
FROM public."Users"
JOIN public."Relationships"
ON public."Users".id = public."Relationships".followingId
AND public."Relationships".followerId = a user ID
I am not really clear about followerId and followingId mean but you can change them in the query if it is not what you want.

SQL Query: User/Group/Role and UserGroup/GroupRole Connecting User to Role

Good evening,
I have been struggling with what I think should be a fairly basic SQL query, but I can't seem to figure it out. Particularly because it seems as if there are multiple approaches (joins/ sub-queries).
I have three primary tables, and two tables connecting them.
USER
uID - PK
name, email, ...
GROUP
gID - PK
name
ROLE
rID - PK
permission
USERGROUP
uID - FK
gID - FK
GROUPROLE
gID - FK
rID - FK
These are many to many relationships, such that a user can be in multiple groups, and a group can have multiple roles.
I would like to have a query that ultimately gives me all of the roles that are connected to a given user through the groups that he belongs. Thus the uID is known, but nothing else. The output could have as few as one column with the rID, as that is all I really need for the program logic.
Is it possible to perform a query on the result of a previous query? I can easily find all the groups a user is in, and given each group, I can easily find the roles associated, but I get tripped up by the fact that there are many groups associated with a user, not just a single one which would be easier.
I would appreciate any help!
Thanks in advance.
This is just joins and aggregation:
select array_agg(distinct r.permission) as permissions
from usergroups ug join
grouproles gr
on ug.gid = gr.gid join
roles r
on gr.rid = r.id
where ug.uid = ?;
If you want the permissions in separate rows, then:
select distinct r.permission
from usergroups ug join
grouproles gr
on ug.gid = gr.gid join
roles r
on gr.rid = r.id
where ug.uid = ?;
I am leaving the distinct because different groups could share the same permissions.

How to select records from database table which has to user id (created_by_user, given_to_user) and replace users id by usernames?

This is task table:
This is user table:
I want to select user tasks.
I would give from backend ("given_to_user) id.
But The thing is I want that SELECTED data would have usernames instead of Id which is (created_by_user and given_to_user).
SELECTED table would look like this.
Example:
How to achieve what I want?
Or maybe I designed poorly my tables that It is difficult to select data I need? :)
task table has to id values that are foreign keys to user table.
I tried many thinks but couldn't get desired result.
You did not design poorly the tables.
In fact this is common practice to store the ids that reference columns in other tables. You just need to learn to implement joins:
SELECT
task.id, task.title, task.information, user.usename AS created_by, user2.usename AS given_to
FROM
(task INNER JOIN user ON task.created_by_user = user.id)
INNER JOIN user AS user2 ON task.created_by_user = user2.id;
Do you just want two joins?
select t.*, uc.username as created_by_username,
ug.username as given_to_username
from task t left join
users uc
on t.created_by_user = uc.id left join
users ug
on t.given_to_user = ug.id;
This uses left join in case one of the user ids is missing.

'Exploratory' SQL queries that uses one criteria to find more criteria

Sorry about this dreadful title. Imagine tables like this: http://sqlfiddle.com/#!9/48d921/1
Here, we run a query for all users with the name "Bob", but we are also interested in all users in the same postcode as "Bob" and also all users of the same "type" as Bob.
You can see I joined the same tables twice to achieve this. The trouble with it is it doesn't scale; the more criteria I want to "explore" the more times I have to join the same tables, making the select statement more cumbersome.
So:
What's the best way to do this?
Does this type of query have a name?
The answer updated
SELECT
FROM user
where u.name="Bob"
OR (u.postcode in (SELECT a.postcode
FROM USER u
JOIN ADDRESS a on a.user=u.id
WHERE u.name="Bob")
)
OR (u.type in (SELECT ut.type
FROM USER u
JOIN USER_TYPE ut1 on u.id=ut1.user
WHERE u.name="Bob")
)
So you scan users table just once for each record checking the linking criteria