SQL Query to select if a value from another exists in current table

I have three tables: Users, Rights and UserRights, which is mapping values from two first tables. Example:

Table ‘Users’

ID LOGIN
1 test1
2 test2

Table ‘Rights’

ID NAME
1 read
2 write

Table ‘UserRights’

USER_ID RIGHT_ID
1 1
2 1
2 2

I need to check whether the user has the appropriate right and I need to output this information inline as true/false with delimiter for each right. So the result should look like this:

LOGIN RIGHTS
test1 read=true;write=false
test2 read=true;write=true

I use Oracle Database

Now I’m using simple query with JOIN, but it’s not applicable in current situation:

SELECT login,
       LISTAGG(name, ';') within GROUP (ORDER BY login) AS UserRights
FROM
  (SELECT u.login,
          r.name
   FROM UserRights ur
   RIGHT JOIN Users u ON ur.user_id = u.id
   LEFT JOIN Rights r ON ur.right_id = r.id)
GROUP BY login;

The output of this select looks like this:

LOGIN UserRights
test1 read
test2 read;write

>Solution :

Here’s one option: cross join users and rights (because you need to check all combinations), and then outer join it to userrights (because you want to check whether that particular combination exists or not).

Sample data:

SQL> with
  2  users (id, login) as
  3    (select 1, 'test1' from dual union all
  4     select 2, 'test2' from dual
  5    ),
  6  rights (id, name) as
  7    (select 1, 'read'  from dual union all
  8     select 2, 'write' from dual
  9    ),
 10  userrights (user_id, right_id) as
 11    (select 1, 1 from dual union all
 12     select 2, 1 from dual union all
 13     select 2, 2 from dual
 14    )

Query:

 15  select u.login,
 16         listagg(r.name ||'='|| case when ur.user_id is not null then 'true' else 'false' end, '; ')
 17         within group (order by r.name) rights
 18  from users u cross join rights r
 19      left join userrights ur on ur.user_id = u.id and ur.right_id = r.id
 20  group by u.login;

LOGIN RIGHTS
----- ------------------------------
test1 read=true; write=false
test2 read=true; write=true

SQL>

Leave a Reply