How to join tables having many to many relationship - sql

I am trying to JOIN four tables together, one table is a joining table as two of the tables have many-to-many relationship:
What would be the query to select DispalyName from User, Name & Description from Role and Permission & Description from Permission.
I know how to join two tables together, but my method of doing so does not work on this problem.
I have tried the following query but it doesn't seem to like it.
SELECT org.[User].[DisplayName], org.[Role].[Description], org.[Permission].[Description]
FROM org.[Role] rolee
JOIN org.[RolePermissions] rolePerms ON rolee.ID = rolePerms.RoleId
JOIN org.[Permission] perms ON rolePerms.PermissionId = perms.ID
WHERE [User].[email] LIKE '%myemail%'

Try this - It seems that You forget to join with the user table
SELECT org.[User].[DisplayName], org.[Role].[Description], org.[Permission].[Description]
FROM org.[User] user Join org.[Role] rolee on user.RoleID = rolee.ID
JOIN org.[RolePermissions] rolePerms ON rolee.ID = rolePerms.RoleId
JOIN org.[Permission] perms ON rolePerms.PermissionId = perms.ID
WHERE org.[User].[email] LIKE '%myemail%'

You need to join User
SELECT u.[DisplayName], r.[Description], p.[Description]
FROM org.[Role] r
JOIN org.[RolePermissions] rp ON r.ID = rp.RoleId
JOIN org.[Permission] p ON rp.PermissionId = p.ID
JOIN org.[User] u ON r.Id = u.RoleID
WHERE u.email LIKE '%myemail%'

Related

Join on two of the same foreign keys

I have this table below
Table Assignments
AssignmentID: int
LinkedTo: varchar(50)
AssignedUser: int
AssignedBy: int
where AssignedBy and AssignedUser are foreign keys from the table Users. Here is what Users looks like
UserKey:int
Username:varchar(50)
How can I do an inner join where I get both AssignedBy and AssignedUser?
The following gives me one of them but how can I get both? By the way AssignedBy and AssignedUser are two different Users. I'm trying to get Users.Username
select Users.Username
from Assignments
INNER JOIN Users ON Assignments.UserKey = Users.UserKey
If you want both user names on one row, you have to join Users twice, like
SELECT UA.Username AS AssignedUserName, UB.Username AS AssignedByUserName
FROM Assignments A
INNER JOIN Users UA ON A.AssignedUser = UA.UserKey
INNER JOIN Users UB ON A.AssignedBy = UB.UserKey;
If your goal is to have all user names regardless wether it comes from AssignedUser or from AssignedBy, you have to use UNION
SELECT U.Username
FROM Assignments A
INNER JOIN Users U ON A.AssignedUser = U.UserKey
UNION SELECT U.Username
FROM Assignments A
INNER JOIN Users U ON A.AssignedBy = U.UserKey;
Note however that this will remove duplicate user names. If you want to keep duplicates, use UNION ALL.
You need two joins:
SELECT assigned.username AS assigned_username
assigned_by.username AS assigned_by_username
FROM assignments a
JOIN users assigned ON a.assigneduser = assigned.userkey
JOIN users assigned_by ON a.assignedby = assigned_by.userkey

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
...

SQL: Join Parent - Child tables

I'm building a simple review website application and need some help with SQL Query.
There are 3 tables (Topics, Comments, Users). I need a SQL query to select the data from all 3 tables.
The 'Topics' table is the parent and the 'Comments' table contains the child records (anywhere from zero to 100 records per parent.
The third table 'Users' contains the user information for all users.
Here are the fields for the 3 tables:
Topics (topicID, strTopic, userID)
Comments (commentID, topicID, strComment, userID)
Users (userID, userName)
I tried:
SELECT *
FROM Topics
Inner Join Comments ON Topics.topicID = Comments.topicID
Inner Join Users ON Topics.userID = Users.userID
But this does not work correctly because there are multiple topics and the User info is not joined to the Comments table. Any help would be appreciated.
You should do left join with Comment to get Topics with no comments and also join Topic and Comment with Users to get related user information for both.
SELECT *
FROM Topics t
INNER JOIN Users tu on tu.userID = t.userID
LEFT JOIN Comments c on c.topicID = t.topicID
LEFT JOIN User cu on cu.userID = c.userID
You need to join to the user table twice.
SELECT *
FROM Topics
INNER JOIN Comments ON Topics.topicID = Comments.topicID
INNER JOIN Users AS u1 ON Topics.userID = u1.userID
INNER JOIN Users AS u2 ON Comments.userID = u2.userID

sqlte3 error no such column

I'm trying to run this command from the shell:
sqlite3 salesShare1.db "
select
UsersSale.saleSpecificProduct,
UsersSale.fAtMall,
Users.name,
Users.gender,
Stores.storeName
FROM
UsersSale
INNER JOIN (Users INNER JOIN Stores ON Users.userID = UsersSale.userID) ON
Stores.storeID = UsersSale.saleStoreID
ORDER BY UsersSale.saleID";
Error: no such column: Users.name
I created all the tables and columns.
sqlite3 salesShare1.db "select * FROM Users ";
1|hezi|0|||
'hezi' is Users.name
What am I doing wrong ?
try please
select us.saleSpecificProduct,
us.fAtMall,u.name,
u.gender,st.storeName
from UsersSale us,Users u,Stores st
where u.userID=us.userID and st.storeID=us.saleStoreID
order by us.saleID
or
select us.saleSpecificProduct,
us.fAtMall,u.name,
u.gender,st.storeName
from UsersSale us
inner join Users u
on u.userID=us.userID
inner join Stores st
on st.storeID=us.saleStoreID
order by us.saleID
hope it helps
Display the schema for your table in the sqlite3 tool and confirm your column name is what you thought it was. Maybe you mis-typed the name.
Your inner join is a little ackward.
Shot in the dark, but my guess is you need to join in the Users table:
select
us.saleSpecificProduct,
us.fAtMall,
u.name,
u.gender,
s.storeName
FROM
UsersSale us
INNER JOIN Users u ON u.userID = us.userID
INNER JOIN Stores s ON s.storeID = us.saleStoreID
ORDER BY us.saleID

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