简体   繁体   中英

postgreSQL - How to have condition on Join model result

I have been pulling my hair on how to translate my business requirement into a SQL query.

The case in itself is not that complex. I have two main tables user and list and a many to many relationship between the 2 of them though the userList table, where a user can be connected to a list by having a specific role, like being the owner or a collaborator.

Relevant properties for that example:

user     -> id 
list     -> id | isPublic (BOOL)
userList -> id | userId | listId | role (OWNER|COLLABORATOR)

I have an API endpoint that allows for a user (requester) to retrieve all the lists of another user (target). I have the following 2 cases:

Case 1 : requester = target

I have that under control with:

`SELECT
  "list".*,
  "userList"."id" AS "userList.id",
  "userList"."listId" AS "userList.listId"
FROM
  "list" AS "list"
INNER JOIN 
  "userList" AS "userList"
  ON "list"."id" = "userList"."listId" AND "userList"."userId" = '${targetUserId}'`;

Case 2 : requester =/= target

This is where I'm stuck as I have the following additional constraints:

  • a user can only see other users' lists that are public
  • OR lists for which they have the role of COLLABORATOR or OWNER

So I'm looking to do something like: Get all the lists for which target is connected to (no matter the role) AND for which, EITHER the list is public OR the requester is also connected to that list.

Sample Data

user table

id
----------
john
anna

list table

id   | isPublic
------------------
1        false
2        true
3        false

userList table

id   |    userId    |  listId    |  role
-          john          1          OWNER
-          john          2          OWNER
-          john          3          OWNER
-          anna          1          COLLABORATOR

Anna requests to see all of John's lists

desired result:

[{
   id: 1,
   isPublic: false
}, {
   id: 2,
   isPublic: true
}]

Any help would be greatly appreciated:)

Many thanks

Does this do what you want?

select l.*
from list
inner join userlist ul on ul.listid = l.id
group by l.id
having 
    bool_or(ul.role = 'OWNER' and ul.userid = 'john')  -- owned by John
    and (l.ispublic or bool_or(ul.userid = 'anna')     -- public or allowed to Anna

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM