Join 2 tables based on a single table - sql

I can't seem to get the join / query that I need!
Lets say I have 3 tables (trimmed for this post...)
user_courses
(int) user_id
(int) course_id
users
(int) user_id
(txt) name
(txt) access
courses
(int) course_id
(txt) course_desc
What I am trying to do is select select all users with a certain access type that are taking a specific course (course_id)
something like...
SELECT *
FROM user_courses uc
JOIN users u
ON uc.user_id = u.user_id
JOIN courses c
ON uc.course_id = c.course_id
WHERE u.access = "foobar"
... but working like I want it to :)
I can get close, but will have extra users that don't have the correct access type.

Use inner join.
SELECT *
FROM user_courses uc
INNER JOIN users u
ON uc.user_id = u.user_id
LEFT JOIN courses c
ON uc.course_id = c.course_id
WHERE u.access = "foobar"

perhaps:
select * from users u
where u.access='foobar'
and exists (select 1 from user_courses uc where uc.user_id=u.user_id)
Cheers

Try
...
WHERE ISNULL(u.access, '') = 'foobar'
Not sure if your 'access' field can be null?

Related

join table on condition

I have 3 tables user, student_data, teacher_data. A user can be either student or a teacher. If it is the teacher I want to join user and teacher_data. And if it is a student then I want to join user with student_data.
How I can do this join with the condition.
I'd combine the two data tables in a sub-query, and then join the users to that.
SELECT
*
FROM
usr u
LEFT JOIN
(
SELECT user_id, datum, xxx, NULL AS yyy FROM student_data
UNION ALL
SELECT user_id, datum, NULL, yyy FROM teacher_data
)
d
ON d.user_id = u.id
https://dbfiddle.uk/?rdbms=oracle_21&fiddle=9b801ea739d42fe50c00ef4e17eaf143
NOTES:
The columns selected from the two data tables must match
Any unmatched columns must either be skipped or filled with NULL
Please don't call a table user, it's a reserved keyword and Oracle won't allow it.
You can write it like this:
select u.user_id,
s.student_id,
t.teacher_id
from usr u
left join student_data s on u.user_id=s.student_id
left join teacher_data t on u.user_id=t.teacher_id
where s.student_id is not null or t.teacher_id is not null
order by u.user_id
For every user_id check if he is a student or teacher, if he is student get his student column values else null, if he is a teacher get his teacher column values else null.
maybe try a union - something like this
select user_id, user_other_stuff
from user, student_data
where user.user_id = student_data.user_id
UNION
select user_id, user_other_stuff
from user, teacher_data
where user.user_id = teacher_data.user_id

SQL Oracle - Multiple count queries on multiple tables

Maybe for some people it might look very simple, but I just cant get it.
My tables are:
CREATE TABLE USERS (user_ID number PRIMARY KEY, username varchar2(32), password varchar2(32));
CREATE TABLE VIDEOS (video_ID number PRIMARY KEY, title varchar(64), description varchar(128));
CREATE TABLE VIEWS (view_ID number PRIMARY KEY, user_ID number, video_ID number);
CREATE TABLE FAVORITES (fav_ID number PRIMARY KEY, user_ID number, video_ID number);
I ve created those separated queries:
SELECT u.username AS "Username", count(*) AS "Views"
FROM Views v, Videos vd, Users u
WHERE v.user_id = u.user_id
AND v.video_id = vd.video_id
GROUP BY u.username
SELECT u.username AS "Username", count(*) AS "Favorites"
FROM Favorites f, Videos vd, Users u
WHERE f.user_id = u.user_id
AND f.video_id = vd.video_id
GROUP BY u.username
And I want a query to show something like that in only one simple query:
Username Views Favorites
-------------------------------
Person1 12 1
Person2 234 21
...
I Googled bunch of similar questions but I couldnt make any of them to work.
So any help is greatly appreciated.
You are progressing on the right track. -> You got two queries and you wish to see them together. You could perform a full outer join to get your results you are looking for as below.
with fave
as (
SELECT u.username AS "Username"
, count(*) AS "Favorites"
FROM Favorites f
JOIN Videos vd
ON f.video_id = vd.video_id
JOIN Users u
ON f.user_id = u.user_id
GROUP BY u.username
)
,views
as (SELECT u.username AS "Username"
, count(*) AS "Views"
FROM Views v
JOIN Videos vd
ON v.video_id = vd.video_id
JOIN Users u
ON v.user_id = u.user_id
GROUP BY u.username
)
select isnull(f.username,v.username) as username
,f.favourites
,v.views
from fave f
full outer join views v
on f.username=v.username
Since you know your data better, you could optimize the query further. Eg: it could be a rule that user who has set a favourite would also have viewed the video. If this is true then you can write a better query to optimize the dataset in a single block, instead of two blocks using full outer join
Aggregate separately in Views:
select user_id, count(*) counter
from Views
group by user_id
and Favorites
select user_id, count(*) counter
from Favorites
group by user_id
and finally LEFT join Users to the above queries:
select u.username,
coalesce(v.counter, 0) Views,
coalesce(f.counter, 0) Favorites
from users u
left join (
select user_id, count(*) counter
from Views
group by user_id
) v on v.user_id = u.user_id
left join (
select user_id, count(*) counter
from Favorites
group by user_id
) f on f.user_id = u.user_id
I used LEFT joins because there may exist users that did not see any video or do not have any favorites. In any of these cases COALESCE() will return 0 instead of null.
The table Videos is not needed.

SQL Query With Join for 2 Tables

I'm unable to form a query with the following tables, which will find out all the Notes from Note table, which is created by any user, who belongs to the logged in user's same company.
Note:
note_id (int),
note_text (varchar),
created_by (int)
User:
user_id (int),
company_id (int)
Logged in user's user id is passed as parameter to the query.
I want to pick up notes from the table Notes where created_by in (user_id of all users whose company_id = company_id of LOGGED_IN_USER)
Please help me to formulate out the query. Looks pretty straight forward, but just can't reach to it's end.
I'm not sure if LOGGED_IN_USER is a table or another object, but if it is a table with the columns you referenced, a join like this would work.
select note_text
from Note n
JOIN User u ON u.user_id = n.created_by
JOIN LOGGED_IN_USER lin ON lin.user_id = u.user_id
and lin.company_id = u.company_id
u might need a Foreign Key for user_id to Notes. and use INNER JOIN
Thanks Vinnie and all for your responses. I finally succeeded to figure out the query. LOGGED_IN_USER_ID is just a numeric parameter which should be passed to the query.
select n.* from Note n where
n.created_by in (
select u1.user_id from User u1 inner join User u2
on u1.company_id=u2.company_id and u2.user_id = :LOGGED_IN_USER_ID*
)
Thanks again.
If i am not misunderstood your question,Try this way
SELECT note_text
FROM Note n
INNER JOIN User u ON u.user_id = n.created_by
WHERE n.created_by= (select u.user_id from User where company_id=LOGGED_IN_USER LIMIT 1 )

Select user details from a self relationship table

I have 3 tables (user, relationship and user_type) with these data (the relevant ones):
USER TABLE:
id, username, avatar, user_type_id
RELATIONSHIP TABLE:
id, user_id1, user_id2, relationship_points
USER_TYPE
id
I'm trying to create a single entry per relationship so, user with id "1" could be in user_id1 OR user_id2 in a relationship, so, I don't have to duplicate unnecessary data.
I already created (thanks to another StackOverflow answer) a query to select all relationship details from an user, but only if it's id is in "user_id1".
SELECT
r.id AS relationship_id,
r.relationship_points AS points,
u.username AS username,
u.avatar_url AS avatar
FROM
relationship AS r
INNER JOIN
user AS u
ON
r.user_id2 = u.id
INNER JOIN
user_type AS t
ON
u.user_type_id = t.id
WHERE
r.user_id1 = ?
But, as you can see, if the user is in "user_id2", it doesn't work.
I know I could make another query, but I think it's the "easy, lazy" way, and I would love to learn how to do this in a single query.
Let me know if this makes the trick:
SELECT
r.id AS relationship_id,
r.relationship_points AS points,
u.username AS username,
u.avatar_url AS avatar
FROM relationship AS r
INNER JOIN user u
ON r.user_id2 = u.id OR r.user_id1 = u.id
INNER JOIN user_type AS t
ON u.user_type_id = t.id
WHERE u.id = ?

MySQL- complex data query in a single statement

Consider the following structure :
alt text http://aeon-dev.org/pap/pap_db.png
Ignore the table user_token.
Now, imagine that you need to get all the roles related to an user, wich may be through it's related groups or directly related to him. In case the same role appears related to a group and the user directly, the role related to the user will prevail over the role given by the group.
Is there any chance this could be done in a single query?
Cheers!
Use:
SELECT DISTINCT r.name AS role_name
FROM USER u
LEFT JOIN USER_HAS_ROLE uhr ON uhr.user_id = u.id
LEFT JOIN USER_HAS_GROUP uhg ON uhg.user_id = u.id
LEFT JOIN GROUP_HAS_ROLE ghr ON ghr.group_id = uhg.group_id
LEFT JOIN ROLE r ON r.id = uhr.role_id
OR r.id = ghr.role_id
WHERE u.username = ?
try this:
Select role_id
From user_has_role
Where userId = #UserId
Union
Select role_id
From user_has_group g
Join Group_has_Role gr
On gr.GroupId = g.GroupId
Where userId = #UserId
This query will get every role a single user has either directly or given by a group
SELECT * FROM ROLE WHERE ID IN (
SELECT ROLE_ID
FROM USER_HAS_ROLE
WHERE USER_ID = 1
UNION
SELECT ROLE_ID
FROM USER_HAS_GROUP UG
INNER JOIN GROUP_HAS_ROLE GR ON UG.GROUP_ID = GR.GROUP_ID
WHERE USER_ID = 1
)
You could find all distinct roles for user 1 like:
select distinct role_id
from (
select uhr.user_id
, uhr.role_id
from user_has_role uhr
union all
select uhg.user_id
, ghr.role_id
from user_has_group uhg
join group_has_role ghr
on ghr.group_id = uhg.group_id
where not exists
(
select *
from user_has_role uhr
where uhr.user_id = uhg.user_id
and uhr.role_id = ghr.role_id
)
) user2role
where user_id = 1
Not sure how a role related to a user should "prevail", but you can assign priorities to them in the union.