Display Interactive Report for different roles sql query - sql

I'm stuck on something, and need some hep with a SQL query. I've created an interactive report with the following SQL query:
SELECT *
FROM FORM f
LEFT OUTER JOIN MANAGER m ON m.MID = f.MID
LEFT OUTER JOIN USERS u ON u.ID = m.ID
LEFT OUTER JOIN MANAGER m2 ON m2.MID = f.MANID
LEFT OUTER JOIN USERS u2 ON u2.ID = c.ID
WHERE lower(u.username) = lower(:session_user_name)
OR lower(u2.username) = lower(:session_user_name);
The logged in user can have different roles in the form. Depending on the role the id of the manager will be set in different columns of the table.
However, all reports for which the user has been entered,regardless of the role in the form, should still be displayed.
With this query, however, I only see one line for which the has been entered as a Manager.
I don't know much about SQL and don't quite understand what the problem is, can someone help here?
Tried with union :
select *
FROM FORM f
LEFT OUTER JOIN MANAGER m ON m.MID = f.MID
LEFT OUTER JOIN USERS u ON u.ID = m.ID
where lower(u.username)=lower(:session_user_name)
union
select *
FROM FORM f2
LEFT OUTER JOIN MANAGER m2 ON m2.MID = f2.MANID
LEFT OUTER JOIN USERS u2 ON u2.ID = m2.ID
where lower(u2.username)=lower(:session_user_name)
Table form:
create table form (FORMID, COLUMN1 varchar2(50), MID NUMBER,MANID NUMBER);
MID and MANID are foreign keys to the table MANAGER
create table manager (MID number, COLUMN1 varchar2(30));
Example:
Here is a table with some sample data:
In the interactive report the manager with the id 15, should see both entries like this
But now he only gets to see one row, the upper row.

Related

SQL Where on different table

SELECT * FROM student_mentor sm INNER JOIN users u
ON sm.student_id = u.user_id
WHERE sm.teacher_id = $teacher_id
Teacher_id being the session id,
I want to see all the students that have the same mentor.
Right now if I run this I just see all of the students twice, maybe one of you knows why?
My db scheme
You are not specifying on which columns you want to do the join, so you're getting a cross reference where all records are joined to all records.
You should do something like (not sure about your column names):
SELECT * FROM student_mentor sm INNER JOIN users u
ON sm.student_id = u.user_id
WHERE sm.teacher_id = $teacher_id

Sql match id's with names from a table that matches with another table

I have a table friend which has two columns with Id's that belong to specific usernames. See example:
Id_Gebruiker is the user and Id_Gebruiker2 is the friend of the user.
The table friend has id's that belong to the table user.
Then that table user has Foreign Keys (column Id_Client) to the table client (referencing the Id_Client column). The client table contains the usernames.
Now I want to get the corresponding usernames that belongs to the Id's that the Friend table contains. So far I got it working when I use only two tables but I can't get it to work with three tables.
Something like this?
select f.Id_Gebruiker, f.Id_Gebruiker2, u.Id_Client, c.Gebruikersnaam
from friend f
join [user] u on f.Id_Gebruiker2 = u.Id
join client c on u.id_client = c.id
EDIT Assuming the names of the users are on the same table (client) and that every friend.Id_Gebruiker corresponds to a client.Id (so there exists a FK relationship), you can find both names with an extra join:
select c.Gebruikersnaam as UserName, c2.Gebruikersnaam as FriendName
from friend f
join client c on f.Id_Gebruiker = c.Id
join [user] u on f.Id_Gebruiker2 = u.Id
join client c2 on u.id_client = c2.id
Here is another answer that you can check and verify at http://sqlfiddle.com/#!3/2b9dd/1.
The main query for getting names for userid and friendid in friends table is as below.
SELECT f1.userid,
f1.friendid,
y.username AS UserName,
x.username AS FriendName
FROM friends f1
INNER JOIN (SELECT DISTINCT f.friendid,
c.clientname AS UserName
FROM users u
INNER JOIN clients c
ON u.id_client = c.id
INNER JOIN friends f
ON f.friendid = u.id) x
ON f1.friendid = x.friendid
INNER JOIN (SELECT DISTINCT f.userid,
c.clientname AS UserName
FROM users u
INNER JOIN clients c
ON u.id_client = c.id
INNER JOIN friends f
ON f.userid = u.id) y
ON f1.userid = y.userid;

SQL 2 Inner Joins on the same field

I have 3 tables as seen from the image below. I have been able to join the projects.project_id to the sprints.project_id and the projects.manager_id to the users.user_id however, also want to join the users.user_id to the projects.product_owner_id I had tried to
INNER JOIN users ON projects.manager_id = users.user_id
AND projects.product_owner_id = users.user_id
Although this returned now results. I want in my list view to be able to list the Manager ID and Products Owner ID in a ListView Control.
Below is my current SQL Query any help would be appreciated.
SELECT
projects.project_name, projects.manager_id,
projects.product_owner_id, projects.project_description,
projects.status,
sprints.sprint_name, sprints.sprint_start_date,
sprints.sprint_length, sprints.work_mon,
sprints.work_tue, sprints.work_wed, sprints.work_thu,
sprints.work_fri, sprints.work_sat, sprints.work_sun,
projects.project_id, sprints.project_id AS Expr1,
sprints.sprint_id, users.username
FROM
projects
INNER JOIN
users ON projects.manager_id = users.user_id
INNER JOIN
sprints ON projects.project_id = sprints.project_id
WHERE
(projects.project_id = #project_id)
Replace inner join with left outer join (since there are products without owner filled) and make a separate join the two associations - manager and owner:
...
INNER JOIN users manager ON projects.manager_id = manager.user_id
LEFT OUTER JOIN users owner ON projects.product_owner_id = owner.user_id
...

Left join with where clause is not working

I am trying to get all the users in my DB which have or do not have requests of friendship, but if they do have requests of friendship, I do not want the ones where a particular user is part of that request of friendship.
My stored procedure is named getNotFriendsOfUser.
This is the query :
select * from user a left join request b on a.idPerson = b.idRequester
inner join persona c on a.idPerson = c.idPerson
where b.idRequester <> #idPerson
There are no friendship relationships on my database and there are more than 10 users to test, but I do not find WHY this query is always returning an empty set of values.
This does give results btw :
select * from user a left join request b on a.idPerson = b.idRequester
inner join persona c on a.idPerson = c.idPerson
Help?
then use a subquery or derived table with your left join for the results you want to omit and exclude them on the primary key.

joining one table multiple times to other tables

I have three tables:
Table User( userid username)
Table Key( userid keyid)
Table Laptop( userid laptopid)
i want all users who have either a key or a laptop, or both. How do i write the query so that it uses a join between table User and table Key, as well as a join between table User and table Laptop?
The main problem is that in the actual scenario, there are twelve or so table joins, sth like:
" select .. From a left join b on (...), c join d on (..),e,f,g where ...",
and i see that a could be joined to b, and a could also be joined to f. So assuming i can't make the tables a,b, and f appear side-by-side, how do i write the sql query?
You can use multiple joins to combine multiple tables:
select *
from user u
left join key k on u.userid = k.userid
left join laptop l on l.userid = u.userid
A "left join" also finds users which do not have a key or a laptop. If you replace both with "inner join", it would find only users with a laptop and a key.
When a "left join" does not find a row, it will return NULL in its fields. So you can select all users that have either a laptop or a key like this:
select *
from user u
left join key k on u.userid = k.userid
left join laptop l on l.userid = u.userid
where k.userid is not null or l.userid is not null
NULL is special, in that you compare it like "field is not null" instead of "field <> null".
Added after your comment: say you have a table Mouse, that is related to Laptop, but not to User. You can join that like:
select *
from user u
left join laptop l on l.userid = u.userid
left join mouse m on m.laptopid = l.laptopid
If this does not answer your question, you gotta clarify it some more.
select distinct u.userid, u.username
from User u
left outer join Key /* k on u.userid = k.userid */
left outer join Laptop /* l on u.userid = l.userid */
where k.userid is not null or l.userid is not null
EDIT
"The main problem is that in the actual scenario, there are twelve or so table joins, sth like:
" select .. From a left join b on (...), c join d on (..),e,f,g where ...",
and i see that a could be joined to b, and a could also be joined to f. So assuming i can't make the tables a,b, and f appear side-by-side, how do i write the sql query?"
You can have as many left outer joins as required. Join the table with the primary key to the rest of the tables or on any other field where field values of one table should match field values of other table.
eg will explain better than words
select *
from a
left outer join b on a.pk = b.fk -- a pk should match b fk
left outer join c on a.pk = c.fk -- a pk should match c fk
left outer join d on c.pk = d.fk -- c pk should match d fk
and so on
-- // Assuming that a user can have at max 1 items of each type
SELECT u.*
-- // Assuming that a user can have more then 1 items of each type, just add DISTINCT:
-- // SELECT DISTINCT u.*
FROM "User" u
LEFT JOIN "Key" u1 ON u.UserID = u1.UserID
LEFT JOIN "Laptop" u2 ON u.UserID = u2.UserID
LEFT JOIN "Server" u3 ON u.UserID = u3.UserID
-- // ...
WHERE COALESCE(u1.UserID, u2.UserID, u3.UserID /*,...*/) IS NOT NULL
As you described the case, you only wanted to know if someone has a laptop or a key. I would write the query with a subquery rather than a join:
select *
from user
where userid in (select userid from key union select userid from laptop)
The reason for this is that by a join a person with multiple laptops or multiple keys will be listed several times (unless you use distinct). And even you use distinct you end up with a less efficient query (at least on Oracle the query optimizer doesn't appear to be able to create an efficient plan).
[Edited to correct what Rashmi Pandit pointed out.]
Solution one:
SELECT * FROM [User] u
INNER JOIN [Key] k
ON u.userid = k.userid
UNION
SELECT * FROM [User] u
INNER JOIN Laptop l
ON u.userid = l.userid
[...]
Solution two:
SELECT * FROM [User] u
LEFT JOIN [Key] k
ON u.userid = k.userid
LEFT JOIN Laptop l
ON u.userid = l.userid
LEFT JOIN [...]
WHERE k.userid IS NOT NULL
OR l.userid IS NOT NULL
OR [...]
Just a guess, also you could check the execution plan for theses two to see if the UNION one is heavier or vice versa.
SELECT *
FROM User
LEFT JOIN Key ON User.id = Key.user_id
LEFT JOIN Laptop ON User.id = Laptop.user_id
WHERE Key.id IS NOT NULL OR Laptop.id IS NOT NULL