How do I display matching rows for multiple users in Postgres? - sql

I'm new to Postgres and I'm looking to retrieve a list of courses that a particular set of users are enrolled in as course leaders in the same course(s). Hopefully I've explained that clearly.
It's returning a list of all the courses that that all the users are enrolled in as course leader rather than a list of the same courses that they are enrolled in as course leader.
This is my original query
select distinct(cm.course_id), cm.course_name, cm.dtcreated, cm.dtmodified
from course_main cm
inner join course_users cu on cm.pk1 = cu.crsmain_pk1
inner join users u on u.pk1 = cu.users_pk1
where u.user_id IN ('msassar5','mfztsjc3', 'mzysshba', 'mftssag3', 'mfztslmi', 'mfztsml7', 'mtlsscm5', 'msdsshp2', 'mzysscp9', 'mcyssmy')
and role = 'P' - 'P' denotes course leader
and cm.service_level = 'F' -- 'F' denotes full course
order by cm.course_id, cm.dtcreated asc
I need to compare all the courses that each of the users are enrolled in as course leader (P) and only display the courses that are in each list, but I'm not sure the best approach.
I've read about the INTERSECT statement and using that does produce the result I expect, but that seems to be an inelegant solution as I would have to add another query to the INTERSECT list for each additional user.
Here is me INTERSECT query
select distinct(cm.course_id), cm.course_name, cm.dtcreated, cm.dtmodified
from course_main cm
inner join course_users cu on cm.pk1 = cu.crsmain_pk1
left outer join users u on u.pk1 = cu.users_pk1
where u.user_id = '<USERNAME>'
and role = 'P'
and cm.service_level = 'F'
intersect
select distinct(cm.course_id), cm.course_name, cm.dtcreated, cm.dtmodified
from course_main cm
inner join course_users cu on cm.pk1 = cu.crsmain_pk1
left outer join users u on u.pk1 = cu.users_pk1
where u.user_id = '<USERNAME>'
and role = 'P'
and cm.service_level = 'F'
intersect
...
...
...
Here is my result, which is correct. This is the only course that ALL the users in my query are enrolled in
cm.course_id -> "I3016-BMAN-62082-1201-2SE-005000"
cm.course_name -> "BMAN62082 The Management of International Organizational Change 2020-21 2nd Semester"
Date Created -> 2020-08-24 11:30:22.064
Date Modified -> 2020-08-24 11:32:45.978
Is there a more elegant solution?
Any help will be appreciated.
thanks

If you want an intersection -- that is courses where all 10 users are leaders -- then use aggregation and a having clause:
select cm.course_id, cm.course_name, cm.dtcreated, cm.dtmodified
from course_main cm join
course_users cu
on cm.pk1 = cu.crsmain_pk1 join
users u
on u.pk1 = cu.users_pk1
where u.user_id in ('msassar5', 'mfztsjc3', 'mzysshba', 'mftssag3', 'mfztslmi', 'mfztsml7', 'mtlsscm5', 'msdsshp2', 'mzysscp9', 'mcyssmy') and
role = 'P' and
cm.service_level = 'F' -- 'F' denotes full course
group by cm.course_id
having count(*) = 10;

Related

Get all data for an entity from another table in one query

I have this query
select *
from (
select c.*,p.name as project_name,u.firstname || ' ' || u.lastname as fullname, u.email as owner_email, u.payment_method, u as user, u.id as user_id, u.api_id, u.api_key,
v.name as vendor_name, v.exid as vendor_id, s.number as sim_number, vm.exid as vendor_model_id, vm.name as vendor_model_name, cr.status as is_recording,
cr.storage_duration as cloud_recording_storage_duration, cr.schedule as schedule, cr.frequency as frequency,
(select count(id) as total from camera_shares cs where c.id=cs.camera_id) as total_share
from cameras c
inner JOIN users u on c.owner_id = u.id
left JOIN projects p on c.project_id = p.id
left JOIN sims s on c.id = s.camera_id
left JOIN vendor_models vm on c.model_id = vm.id
left JOIN vendors v on vm.vendor_id = v.id
left JOIN cloud_recordings cr on c.id = cr.camera_id
) c
this gives me all cameras and with all relevant values which I require.
now there is another table, snapshot_extractors and it has a relation with the camera on id and camera_id in extractors table, as one camera can have more than 1 extractors.
In the above query, I want to get all extraction for one camera, I can do it in a separate query, but is it possible to get all extractions in the above query as an array of all extractions for a camera?
You can use another correlated subquery:
(select array_agg(e.extraction)
from snapshot_extractors e
where e.camera_id = c.camera_id
)

Sum subquery Oracle

I'm doing a SQL query and I'm trying to sum the result of my subquery, but without success. The command does not execute
Can someone help me?
The query I'm doing is:
SELECT cm.course_id,cm.course_name, sum (select max(SCORE) from
ATTEMPT where GRADEBOOK_GRADE_PK1 = GG.PK1 group by 1)
FROM gradebook_main gm
JOIN course_main cm ON cm.pk1 = gm.crsmain_pk1
JOIN gradebook_grade gg ON gm.pk1 = gg.gradebook_main_pk1
JOIN course_users cu ON cu.pk1 = gg.course_users_pk1
JOIN users u ON u.pk1 = cu.users_pk1
WHERE U.user_id = '1616894251'
group by cm.course_id, cm.course_name
Thanks!
I have tried build you subselect as joined table ..hopre the group by column is GRADEBOOK_GRADE_PK1
SELECT
cm.course_id
, cm.course_name
, sum ( t.max_score
)
FROM gradebook_main gm
JOIN course_main cm ON cm.pk1 = gm.crsmain_pk1
JOIN gradebook_grade gg ON gm.pk1 = gg.gradebook_main_pk1
JOIN course_users cu ON cu.pk1 = gg.course_users_pk1
JOIN users u ON u.pk1 = cu.users_pk1
JOIN (
select GRADEBOOK_GRADE_PK1, max(SCORE) max_score
from ATTEMPT
group by GRADEBOOK_GRADE_PK1
) t on t.GRADEBOOK_GRADE_PK1 = GG.PK1
WHERE U.user_id = '1616894251'
group by cm.course_id, cm.course_name

Postgres hangs when a possible null column value is used in SELECT statement

I'm trying to mash some user data from several tables together in Postgres in order to display information in a table on a web page. Users may or may not have "contact" information, and I'm trying to include the "contact" email address as part of what gets returned in the select query.
The query I'm using boils down to the following:
select u.user_id, r.role_id, u.first_name, u.last_name, c.email, o.state_active, ce.name
from user
join user_role r on u.user_id = r.user_id
join company c on r.company_id = c.company_id
join object_state o on u.state_id = o.state_id
left outer join user_contact uc on u.user_id = uc.user_id and uc.default_flag = 'Y' and uc.status = 'A'
left outer join contact c on uc.contact_id = c.contact_id and c.contact_type like 'E%'
I keep running into problems around the outer joined tables at the bottom. It appears that if I do a SELECT * sort of query, I'll get back everything I expect, but as soon as I run the above query, the statement just hangs and never returns values. If, however, I remove the c.email portion of the select statement, everything returns quickly with no problems at all.
Am I missing some sort of core feature of Postgres where I'm unable to select a column that might be null, or is there something else obvious that I'm completely missing as far as this query goes? I don't understand why it works fine if I don't require the email, but not otherwise.
Could you provide a sqlfiddle with a sample of your database to test our solutions please ?
You can try this :
select u.user_id, r.role_id, u.first_name, u.last_name, COALESCE(c.email,NULL), o.state_active, ce.name
from user
join user_role r on u.user_id = r.user_id
join company c on r.company_id = c.company_id
join object_state o on u.state_id = o.state_id
left outer join user_contact uc on u.user_id = uc.user_id and uc.default_flag = 'Y' and uc.status = 'A'
left outer join contact c on COALESCE(uc.contact_id,-1) = c.contact_id and c.contact_type like 'E%'
Here, you should look at the COALESCE.

sql select query among 3 tables

I have three tables:
ITEMDISPLAYCOuNTS *this table stores who displayed which posts and howmanytimes
postid, count, whodisplayedid
POSTS *this table stores who posted what?
postid, whopostedid
ASPNET_USERS
userid, username
What I want at the end is who displayed whose post, and how many times, with usernames, not userids:
OUTPUT
UserNameWhoDisplayed, UserNameWhosePost, Count
I wrote the following code, but it is not functioning properly.
SELECT u1.UserName, u2.UserName, ItemDisplayCounts.Count
FROM ItemDisplayCounts AS i, Posts AS p, aspnet_Users AS u1, aspnet_Users AS u2
WHERE p.UserId = u2.UserId AND i.UserId = u1.UserId AND i.PostId = p.PostId
Can anyone suggest any corrections?
I think you want something like this (changed your joins to proper ANSI ones):
select
iu.UserName as UserNameWhoDisplayed,
pu.UserName as UserNameWhosePost,
sum(i.Count) as [Count]
from ItemDisplayCounts as i
inner join aspnet_Users as iu on iu.userid = i.whodisplayedid
inner join posts as p on p.postid = i.postid
inner join aspnet_Users as pu on pu.userid = p.whopostedid
group by
iu.UserName,
pu.UserName
If I am understanding you correctly you do not need to perform any math in the query, since you have the count field in the ITEMDISPLAYCOuNTS table. So, I do believe this will work for you:
SELECT U2.username AS UserNameWhoDisplayed,
U1.username AS UserNameWhosePost,
ID.[Count]
FROM ((POSTS AS P
INNER JOIN ASPNET_USERS AS U1 ON P.whopostedid = U1.userid)
INNER JOIN ITEMDISPLAYCOuNTS AS ID ON P.postid = ID.postid)
INNER JOIN ASPNET_USERS AS U2 ON ID.whodisplayedid = U2.userid

SQL join help for friend list

I have three database tables: users, user_profiles and friends:
users
id
username
password
user_profiles
id
user_id
full_name
friends
id
usera_id
userb_id
What would be a query which finds the friends list of any user and also joins the table users and user_profiles to get the profile and user information of that friend?
Use:
SELECT f.username,
up.*
FROM USERS f
JOIN USER_PROFILES up ON up.user_id = f.id
JOIN FRIENDS fr ON fr.userb_id = f.id
JOIN USERS u ON u.id = fr.usera_id
WHERE u.username = ?
...assuming userb_id is the friend id.
This may not be the best way to do it, but this felt like the logical way:
select a.id , a.friend_id ,
Users.username
from
( SELECT id , IF(usera_id = 1, userb_id , usera_id) friend_id
FROM friends
where usera_id = 1 OR userb_id = 1 ) a
left join Users on a.friend_id = Users.id
this uses a mySQL function so probably wont work in Oracle/MSSQL
Falling back on bad habits (not using JOIN notation in the FROM clause):
SELECT a.id, a.username, a.full_name,
b.id, b.username, b.full_name
FROM friends AS f, users AS ua, users AS ub,
user_profiles AS a, user_profiles AS b
WHERE f.usera_id = ua.id
AND f.userb_id = ub.id
AND a.user_id = ua.id
AND b.user_id = ub.id
The key point is using table aliases (all those 'AS' clauses) and referencing the same table more than once when necessary.
Someone could write this with JOIN instead.
Some modification to eugene y's answer, will this work?
SELECT * FROM users u
JOIN friends f ON (f.userb_id = u.id OR f.usera_id = u.id)
JOIN user_profiles p ON u.id = p.user_id
WHERE u.id = ?