Select user details from a self relationship table - sql

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 = ?

Related

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.

How to design correct data model for related tables using sql joins?

I have a Organization table with relationship as 'One Org' will have 'multiple Suborg' and 'exactly 2 supervisors'. The Supervisors RoleID is mapped to Roles Table 'ID' along with other roles.
Organization table: ID, OrgName, OrganizationTypeID,OrgModifiedDate
OrganizationType : ID, TypeName
SubOrg Table : ID, OrgID, SubOrgName, SuborgModifiedDate
Users Table : Id, RoleID , RoleName, OrgID, SubOrgID, UserModifiedDate
The relationship is One Organization can have multiple organization and the number of Supervisor in every Organization are 2.
When I am joining the above table with the below query, it gives me multiple rows of repeating data.
select distinct
o.id OrgID,
o.name as OrgName,
ot.Name as orgTypeName,
isnull (o.ModifiedOn, o.Createdon) as Org_ModifiedDate,
s.id SubOrgID,
s.name as suborgName,
isnull(s.ModifiedOn,s.CreatedOn) as SubOrg_ModifiedDate,
u.Name SupervisorName,
u.RoleID SupervisorID,
u.id UserID
from users u left join Organizations o on U.OrgID = o.id
left join Suborganizations s on s.orgID = o.Id
left join OrganizationTypes ot on o.OrganizationTypeid = ot.id
where U.RoleID = '9774904F-E74E-4F59-9552-FB3DC233D25B'
How do I achieve in my PowerBI model where I have to show data in a table like the picture below,
I believe you should only break the tables into more when its required. As in above I dont think so, if it does contribute to any good with normalizing suborgs to suborgs table and other etc. Rather have only 2 tables
Organization and Users
Organization table:
ID, TypeName,OrgName
SubOrgName, OrgModifiedDate
, SuborgModifiedDate
Users Table:
Id, RoleID , RoleName, OrgID,
UserModifiedDate
Query
Select column1, column2.... From
users u left join Organizations o on
u.Id=o.Id where where U.RoleID =
'9774904F-E74E-4F59-9552-
FB3DC233D25B'

H2 making one select from 2

I got 3 tables, Users, courses and course realation tables. I want to get users who aren't on specific course. So I figure I need somehow merge 2 selects with right join. How could I make one select from 2 selects?
SELECT ID, NAME, LASTNAME, ROLE FROM COURSERELATION JOIN USERS ON
ID_USER = ID WHERE ID_COURSE = ?
RIGTH JOIN
SELECT ID, NAME, LASTNAME, ROLE from COURSERELATION JOIN USERS ON
ID_USER = ID WHERE ID_COURSE != ?
You need to extract users for which it doesn't exist a record of that user for the specific course. You can filter the rows using a NOT EXISTS clause over a subquery.
Please try below query:
SELECT u.ID,
u.NAME,
u.LASTNAME,
u.ROLE
FROM USERS u
WHERE NOT EXISTS (SELECT 1
FROM COURSERELATION s
WHERE s.id_user = u.id
AND s.id_course = 'YOUR_COURSE_ID_HERE' )

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 )

Get data from 3 database tables

I have 3 tables
Users - columns id, userName,...
Comment - columns id, text, userId, roomId
CommentRate - columns userId, commmentId
CommentRate table contain userId's that liked this comment identified by commentId.
I want to select all comments (id, text, roomId, userId, userName, []ListOfLikes) from Comment table by roomId where []ListOfLikes should contain userId, userName.
You can refer the same table ( USER in this case) more times with different join criteria using aliases, but It is not possible to convert values in field names. This statement will extract all that you need, but repeating rows and not adding columns:
SELECT C.ID, C.TEXT, C.ROOMID, U.USERNAME, U2.USERNAME
FROM COMMENT C
INNER JOIN COMMENTRATE CR ON C.ID = CR.COMMENTID
INNER JOIN USERS U ON C.USERID = U.ID
INNER JOIN USERS U2 ON CR.USERID = U2.ID
WHERE U.USERNAME IN ('username1', 'username2')
ORDER BY C.ROOMID
If you want to filter by users that likes, you could replace U with U2 in the WHERE line of code.