Reputation: 123
I have two tables with a Many to Many relationship:
TABLE USER(id, name, ...)
TABLE GROUP(id, name, ...)
TABLE USER_GROUP(user_id, group_id)
Given a list of usernames, I want my backend to send an SQL query to the database.
This query must select all groups (from table GROUP
) which contain at least all users (from table USER
) specified in the input list.
Please note that the input list contains the usernames and not the user ids.
Requirements:
Expected results:
Input list (usernames) | Expected result (groups) |
---|---|
John , Celia |
Group A , Group C |
John , Jack , Celia |
Group A |
Jack |
Group A , Group B |
Data :
Table USER
+------+-------------------+
| ID | NAME |
+------+-------------------+
| 1 | John |
| 2 | Jack |
| 3 | Celia |
| 4 | Alice |
+------+-------------------+
Table GROUP
+------+-------------------+
| ID | NAME |
+------+-------------------+
| 1 | Group A |
| 3 | Group B |
| 4 | Group C |
| 5 | Group D |
+------+-------------------+
Table USER_GROUP
+-----------+-------------------+
| GROUP_ID | USER_ID |
+-----------+-------------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 3 | 1 |
| 3 | 3 |
| 3 | 4 |
+-----------+-------------------+
EDIT:
I use PostgreSQL as my RDBMS
Upvotes: 2
Views: 331
Reputation: 1269803
Let me assume that you are passing the values in as an array. You can use:
select g.name
from groups g join
user_groups ug
on ug.group_id = g.id join
users u
on ug.user_id = u.id
where u.name = any (:input_list)
group by g.name
having count(*) = cardinality(:input_list);
Here is a db<>fiddle, with the data fixed to match the results you have in the question.
Upvotes: 1
Reputation: 1
CREATE TABLE Users (User_ID INT, Name VARCHAR(255)); CREATE TABLE Groups (Group_ID INT, Name VARCHAR(255)); CREATE TABLE User_Group (User_ID INT , Group_ID INT); INSERT INTO Users (User_ID,Name) VALUES (1,'John'),(3,'Celia'); INSERT INTO Groups (Group_ID,Name) VALUES(1,'Group A'),(4,'Group C'); INSERT INTO User_Group(User_ID, Group_ID) VALUES(1,1),(3,4);
SELECT string_agg(U.Name::text, ',') AS UserNames ,string_agg(G.Name::text, ',') AS GroupNames FROM User_Group AS UG INNER JOIN Users AS U ON U.User_ID=UG.User_ID INNER JOIN Groups AS G ON G.Group_ID=UG.Group_ID WHERE U.Name IN ('John','Celia')
usernames | groupnames :--------- | :-------------- John,Celia | Group A,Group C
db<>fiddle here
Upvotes: 1