MOODLE SQL only return results where user is in same group student - moodle

SELECT ra.id,
DATE_FORMAT(FROM_UNIXTIME(ra.timemodified),'%d-%m-%Y') AS Enrolment_Date,
c.fullname,
IFNULL(cmc.completed, 0) as 'Activities Completed',
u.firstname,
u.lastname,
DATE_FORMAT(FROM_UNIXTIME(cc.timecompleted),'%d-%m-%Y') AS complete_date,
CONCAT('<a target="_new" href="%%WWWROOT%%/user/profile.php?id=',ra.userid,'">', u.firstname, ' ', u.lastname, '</a>') AS Username
FROM prefix_role_assignments AS ra
JOIN prefix_user u ON ra.userid = u.id
JOIN prefix_context AS ctx ON ctx.id = ra.contextid
JOIN prefix_course c ON c.id = ctx.instanceid
JOIN prefix_enrol e ON e.courseid = c.id
JOIN prefix_user_enrolments ue ON ue.enrolid = e.id AND ue.userid = u.id
LEFT JOIN prefix_course_completions cc ON cc.course = c.id AND cc.userid = u.id
LEFT JOIN prefix_grade_items gi ON gi.courseid = c.id AND gi.itemtype = 'course'
LEFT JOIN prefix_grade_grades g ON g.itemid = gi.id AND g.userid =u.id
LEFT JOIN (SELECT cmc.userid, cm.course, COUNT(cmc.id) as completed FROM prefix_course_modules_completion cmc, prefix_course_modules cm WHERE cm.visible = 1 AND cmc.coursemoduleid = cm.id AND cmc.completionstate IN ('1','2') GROUP BY cm.course, cmc.userid) cmc ON cmc.course = c.id AND cmc.userid = u.id
WHERE u.id > 0 AND (c.id IN(
SELECT DISTINCT(ctx.instanceid) as id
FROM prefix_role_assignments ra JOIN prefix_context ctx ON ra.contextid = ctx.id
WHERE ra.userid = %%USERID%% AND ctx.contextlevel = 50 AND ra.roleid IN ('1','9','2','3','4','10'))
OR c.id IN(
SELECT distinct(c.id) as id FROM prefix_role_assignments ra
JOIN prefix_context ctx ON ra.contextid = ctx.id
JOIN prefix_course c ON c.category = ctx.instanceid
WHERE ra.userid = %%USERID%% AND ctx.contextlevel = 40 AND ra.roleid IN ('1','9','2','3','4','10'))
) AND u.deleted = 0 AND u.suspended = 0 AND u.username <> 'guest' AND c.visible = 1 AND ue.status = 0 AND e.status = 0 AND ra.roleid = '5'
GROUP BY ra.userid, ctx.instanceid HAVING u.firstname LIKE 'student' ESCAPE '\\'
Hi all,
Im struggling here, I cant seem to get how to only return results from the above query where the user running the query (%%USERID%%) shares the same groups as the student. This is a query cobbled together from a number of other queries and works perfectly except for that one thing.
Ive tried to tack on the following in various ways into this but cant get it to work at all
SELECT g.name, gm.groupid, u.firstname
FROM mdl_groups as g
JOIN mdl_groups_members as gm ON g.id = gm.groupid
JOIN mdl_user as u ON u.id = gm.userid AND u.id = 'student', %%USERID%%'
Any help at all even a point in the right direction would be great, this isnt my job role as such but Ive been tasked to make something like this happen.
Thanks for reading

It seems that the subquery boils down to just some userids, but this needs to return rows.
SELECT DISTINCT
gms.userid
FROM mdl_groups_members gms
INNER JOIN mdl_groups_members AS gmu ON gms.groupid = gmu.groupid
WHERE gmu.userid = %%USERID%%
AND gms.userid LIKE 'student%'
If it does then it needs to link to the correct place. Now his is quiet a leap, but and it "might" be used this way: (select * is not recommended, just an abbreviation):
SELECT
*
FROM prefix_role_assignments AS ra
INNER JOIN prefix_user u ON ra.userid = u.id
INNER JOIN (
SELECT DISTINCT
gms.userid
FROM mdl_groups_members gms
INNER JOIN mdl_groups_members AS gmu ON gms.groupid = gmu.groupid
WHERE gmu.userid = %%USERID%%
AND gms.userid LIKE 'student%'
) sg ON ra.userid = sg.userid
INNER JOIN prefix_context AS ctx ON ctx.id = ra.contextid
INNER JOIN prefix_course c ON c.id = ctx.instanceid
INNER JOIN prefix_enrol e ON e.courseid = c.id
INNER JOIN prefix_user_enrolments ue ON ue.enrolid = e.id AND ue.userid = u.id
LEFT JOIN prefix_course_completions cc ON cc.course = c.id AND cc.userid = u.id
LEFT JOIN prefix_grade_items gi ON gi.courseid = c.id AND gi.itemtype = 'course'
LEFT JOIN prefix_grade_grades g ON g.itemid = gi.id AND g.userid = u.id
LEFT JOIN (
SELECT
cmc.userid
, cm.course
, COUNT(cmc.id) AS completed
FROM prefix_course_modules_completion cmc
, prefix_course_modules cm
WHERE cm.visible = 1
AND cmc.coursemoduleid = cm.id
AND cmc.completionstate IN ('1', '2')
GROUP BY
cm.course
, cmc.userid
) cmc ON cmc.course = c.id AND cmc.userid = u.id
WHERE u.id > 0
AND (
c.id IN (
SELECT DISTINCT
(ctx.instanceid) AS id
FROM prefix_role_assignments ra
INNER JOIN prefix_context ctx ON ra.contextid = ctx.id
WHERE ra.userid = %%USERID%% AND ctx.contextlevel = 50
AND ra.roleid IN ('1', '9', '2', '3', '4', '10')
)
OR c.id IN (
SELECT DISTINCT
(c.id) AS id
FROM prefix_role_assignments ra
INNER JOIN prefix_context ctx ON ra.contextid = ctx.id
INNER JOIN prefix_course c ON c.category = ctx.instanceid
WHERE ra.userid = %%USERID%% AND ctx.contextlevel = 40
AND ra.roleid IN ('1', '9', '2', '3', '4', '10')
)
)
AND u.deleted = 0
AND u.suspended = 0
AND u.username <> 'guest'
AND c.visible = 1
AND ue.STATUS = 0
AND e.STATUS = 0
AND ra.roleid = '5'
GROUP BY
ra.userid
, ctx.instanceid
HAVING u.firstname LIKE 'student%' ESCAPE '\\'

Related

Infinite loop when I updated query to add an additional variable

I have this query:
with users_having_connected as (
select u.id as user_id,
(a.connected_at is not null) has_connected
from core_user u
join core_profile p on u.id = p.user_id
join core_conversation c on (c.profile1_id = p.id or c.profile2_id = p.id)
join analytics_connection a on c.id = a.conversation_id
group by u.id, (a.connected_at is not null)
)
select u.id as user_id,
date_trunc('month', u.created at time zone 'UTC')::date as month,
p.community_id,
p.organization_id,
p.profile_type_intention,
(p.basic_account_completed and (p.is_mentor or p.is_entrepreneur)) as profile_is_completed,
exists(select 1 from core_message where core_message.sender_id = p.id) as has_sent_a_message,
(EXISTS (SELECT 1 FROM core_message WHERE core_message.receiver_id = p.id)) AS has_received_a_message,
(EXISTS (SELECT 1 FROM core_admin_conversation_w_resp WHERE core_admin_conversation_w_resp.initiator_id = p.id or core_admin_conversation_w_resp.responder_id = p.id)) AS has_one_by_one,
exists(select 1 from users_having_connected where user_id = u.id) as has_two_by_two
from core_user as u
join core_profile p on u.id = p.user_id
where
p.profile_type_intention is not null
Which worked fine until I added this line:
(EXISTS (SELECT 1 FROM core_admin_conversation_w_resp WHERE core_admin_conversation_w_resp.initiator_id = p.id or core_admin_conversation_w_resp.responder_id = p.id)) AS has_one_by_one,
This specific variable add causes this query to infinite loop. What do I need to do to fix it? Am I missing a set of parentheses somewhere?

Jasper Report: error executing SQL statement by Collection Parameter

I'm creating a report which's passing by collection parameter.
The parameter name as 'ids' and the class is java.util.Collection.
My query:
select * from order_deliveryorder a
left join order_deliveryorderline b on a.id = b.d_order_id
left join order_item c on c.id = b.product_id
left join order_orderline e on e.id = b.s_order_id
left join order_order f on e.order_id = f.id
left join order_itemsection g on g.id = f.section_id
left join order_location d on d.id = a.location_id
left join order_location h on h.id = a.from_location_id
where a.id in ('2377900603251741014','2377900603251740997','2377900603251740967')
the query in jasper:
select * from order_deliveryorder a
left join order_deliveryorderline b on a.id = b.d_order_id
left join order_item c on c.id = b.product_id
left join order_orderline e on e.id = b.s_order_id
left join order_order f on e.order_id = f.id
left join order_itemsection g on g.id = f.section_id
left join order_location d on d.id = a.location_id
left join order_location h on h.id = a.from_location_id
where $X{IN, a.id, ids}
The value of parameter "ids" is ["2377900603251741014","2377900603251740997","2377900603251740967"]
In the End, had met the error executing sql statement.

Double Select into NOT IN

I have this query:
SELECT * FROM (
SELECT DISTINCT on (i.empleado) i.id as id,i.dia as dia,e.id as empleadoId,pe.nombre as personaNombre,pe.apellido1 as personaApellido1,pe.apellido2 personaApellido2 FROM rrhh.imputacion as i
INNER JOIN rrhh.empleado as e ON e.id = i.empleado
JOIN commons.persona AS pe ON e.persona_comun = pe.id
INNER JOIN rrhh.parte__imputaciones as pi ON pi.imputacion = i.id
INNER JOIN rrhh.parte as p ON pi.parte = p.id
WHERE p.borrador = false AND e.fecha_fin_contrato IS NULL AND e.security_domain_id = 2 and e.id
NOT IN(
SELECT DISTINCT on (i.empleado) i.empleado FROM rrhh.imputacion as i
INNER JOIN rrhh.empleado as e ON e.id = i.empleado
JOIN commons.persona AS pe ON e.persona_comun = pe.id
INNER JOIN rrhh.parte__imputaciones as pi ON pi.imputacion = i.id
INNER JOIN rrhh.parte as p ON pi.parte = p.id
WHERE i.dia >= '2017-12-04' AND i.dia <= '2017-12-10' and p.borrador = false AND e.fecha_fin_contrato IS NULL AND e.security_domain_id = 2
ORDER BY i.empleado, i.dia DESC,i.id
)
ORDER BY i.empleado, i.dia DESC,i.id)
t
ORDER BY t.dia DESC
I need to add the query below in the "NOT IN", with an OR:
SELECT DISTINCT on (a.empleado) a.empleado FROM rrhh.ausencia as a
INNER JOIN rrhh.empleado as e ON e.id = a.empleado
JOIN commons.persona AS pe ON e.persona_comun = pe.id
INNER JOIN rrhh.parte__imputaciones as pi ON pi.imputacion = a.id
INNER JOIN rrhh.parte as p ON pi.parte = p.id
WHERE a.dia >= '2017-12-04' AND a.dia <= '2017-12-11' and p.borrador = false AND e.fecha_fin_contrato IS NULL AND e.security_domain_id = 2
ORDER BY a.empleado, a.dia DESC,a.id
There should be something similar to what I put down, but that does not work, because I do not know the syntax, I tried an OR and a UNION, but in both cases I get an error:
SELECT * FROM (
SELECT DISTINCT on (i.empleado) i.id as id,i.dia as dia,e.id as empleadoId,pe.nombre as personaNombre,pe.apellido1 as personaApellido1,pe.apellido2 personaApellido2 FROM rrhh.imputacion as i
INNER JOIN rrhh.empleado as e ON e.id = i.empleado
JOIN commons.persona AS pe ON e.persona_comun = pe.id
INNER JOIN rrhh.parte__imputaciones as pi ON pi.imputacion = i.id
INNER JOIN rrhh.parte as p ON pi.parte = p.id
WHERE p.borrador = false AND e.fecha_fin_contrato IS NULL AND e.security_domain_id = 2 and e.id
NOT IN(
SELECT DISTINCT on (i.empleado) i.empleado FROM rrhh.imputacion as i
INNER JOIN rrhh.empleado as e ON e.id = i.empleado
JOIN commons.persona AS pe ON e.persona_comun = pe.id
INNER JOIN rrhh.parte__imputaciones as pi ON pi.imputacion = i.id
INNER JOIN rrhh.parte as p ON pi.parte = p.id
WHERE i.dia >= '2017-12-04' AND i.dia <= '2017-12-10' and p.borrador = false AND e.fecha_fin_contrato IS NULL AND e.security_domain_id = 2
ORDER BY i.empleado, i.dia DESC,i.id
OR -- UNION
SELECT DISTINCT on (a.empleado) a.empleado FROM rrhh.ausencia as a
INNER JOIN rrhh.empleado as e ON e.id = a.empleado
JOIN commons.persona AS pe ON e.persona_comun = pe.id
INNER JOIN rrhh.parte__imputaciones as pi ON pi.imputacion = a.id
INNER JOIN rrhh.parte as p ON pi.parte = p.id
WHERE a.dia >= '2017-12-04' AND a.dia <= '2017-12-11' and p.borrador = false AND e.fecha_fin_contrato IS NULL AND e.security_domain_id = 2
ORDER BY a.empleado, a.dia DESC,a.id
)
ORDER BY i.empleado, i.dia DESC,i.id)
t
ORDER BY t.dia DESC
I need to add the query below in the "NOT IN", with an OR:
I don't know what you mean by "with an OR". If you mean that e.id should be NOT IN the first subquery OR not in the second subquery, you could do:
...
AND (
e.id NOT IN (
SELECT DISTINCT ...
) OR (
e.id NOT IN (
SELECT DISTINCT ...
)
)
If you don't want it to be in either (hence the attempt at a union) just change the OR to AND.
Although I suspect the query plan for this query will be quite poor. IN and NOT IN are inefficient when there are lots of results in there.
Also the code is quite strange. Most of your joins are explicitly INNER JOINs, but a couple just say JOIN. But JOIN by default is an INNER JOIN. So why are some lines explicit and others implicit? And why the difference in styles throughout the code? Case in point, AS vs as, from one line to the next...

MOODLE - i need a query that returns latest enrolment date in course

this query is not returning correct latest_enrolment date. whenever i enrol a user in course, it doesnot updates enrolment date in database.. can anyone help?
SELECT TRIM(c.id) course_id,TRIM(c.fullname) course_fullname,FROM_UNIXTIME(u.timecreated) as registration ,FROM_UNIXTIME( ra.timemodified ) latest_enrolment_date,COUNT( * ) AS enrol_count
FROM mdl_user u
INNER JOIN mdl_role_assignments ra ON ra.userid = u.id
INNER JOIN mdl_context ct ON ct.id = ra.contextid
INNER JOIN mdl_course c ON c.id = ct.instanceid
INNER JOIN mdl_role r ON r.id = ra.roleid
INNER JOIN mdl_course_categories cc ON cc.id = c.category
WHERE r.id =5 GROUP BY c.id
Something like this
SELECT MAX(ue.timecreated) AS latest_enrolment_date
FROM mdl_enrol e
JOIN mdl_user_enrolments ue ON ue.enrolid = e.id
WHERE e.courseid = xx

Row_Number () Over Certain Value Rows

SELECT
ROW_NUMBER() OVER (PARTITION BY s.ExitStateTypeId ORDER BY s.InsertDate) AS Number
,x.Id
,p.FirstName
,p.LastName
,p.PN
,t.Name
,s.ExitStateTypeId as [Status]
,g.Name
,x.OrganisationId
,d.Name AS Direction
,d.Id AS DirectionId
,h.Name AS Referal
,h.Id AS HealthOrgTypeId
,s.IssueDate
,s.InsertDate
FROM [DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s on x.Id = s.ExitId
INNER JOIN [DB1].[dbo].[HealthOrgTypes] h on x.HealthOrgTypeId = h.Id
INNER JOIN [DB1].[dbo].[Directions] d on x.DirectionId = d.Id
INNER JOIN [DB1].[dbo].[HealthCards] c on x.HealthCardId = c.Id
INNER JOIN [DB2].[pr].[TABLE] p on p.Id = c.TABLEId
INNER JOIN [DB3].[orgs].[Organizations] g on g.Id = x.OrganisationId
INNER JOIN [DB4].[dbo].ExitStateTypes t on t.Id = s.ExitStateTypeId
WHERE s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
ORDER BY s.InsertDate
This is my query, but what I need is that I want only those rows to be enumerated by ROW_NUMBER which s.ExitStateTypeId is in (4,7), for the other rows it should be -1.
Here's the incorrect query just for getting the idea.
SELECT
ROW_NUMBER() OVER (PARTITION BY s.ExitStateTypeId Where s.ExitStateTypeId IN (4,7)
ORDER BY s.InsertDate) AS Number
,x.Id
,p.FirstName
,p.LastName
,p.PN
,t.Name
,s.ExitStateTypeId as [Status]
,g.Name
,x.OrganisationId
,d.Name AS Direction
,d.Id AS DirectionId
,h.Name AS Referal
,h.Id AS HealthOrgTypeId
,s.IssueDate
,s.InsertDate
FROM [DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s on x.Id = s.ExitId
INNER JOIN [DB1].[dbo].[HealthOrgTypes] h on x.HealthOrgTypeId = h.Id
INNER JOIN [DB1].[dbo].[Directions] d on x.DirectionId = d.Id
INNER JOIN [DB1].[dbo].[HealthCards] c on x.HealthCardId = c.Id
INNER JOIN [DB2].[pr].[TABLE] p on p.Id = c.TABLEId
INNER JOIN [DB3].[orgs].[Organizations] g on g.Id = x.OrganisationId
INNER JOIN [DB4].[dbo].ExitStateTypes t on t.Id = s.ExitStateTypeId
WHERE s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
ORDER BY s.InsertDate
So, I want partition by s.ExitStateTypeId just when it is 4 or 7 and -1 for the others
This is data I expect
Perhaps with a combination of CASE and ROW_NUMBER:
SELECT Number = CASE WHEN s.ExitStateTypeId NOT IN (4,7) THEN -1
ELSE Row_number() OVER (
partition BY s.exitstatetypeid
ORDER BY s.insertdate) END,
x.id,
p.firstname,
p.lastname,
p.pn,
t.name,
s.exitstatetypeid AS [Status],
g.name,
x.organisationid,
d.name AS Direction,
d.id AS DirectionId,
h.name AS Referal,
h.id AS HealthOrgTypeId,
s.issuedate,
s.insertdate
FROM [DB1].[dbo].[exits] x
INNER JOIN [DB1].[dbo].[exitstates] s
ON x.id = s.exitid
INNER JOIN [DB1].[dbo].[healthorgtypes] h
ON x.healthorgtypeid = h.id
INNER JOIN [DB1].[dbo].[directions] d
ON x.directionid = d.id
INNER JOIN [DB1].[dbo].[healthcards] c
ON x.healthcardid = c.id
INNER JOIN [DB2].[pr].[table] p
ON p.id = c.tableid
INNER JOIN [DB3].[orgs].[organizations] g
ON g.id = x.organisationid
INNER JOIN [DB4].[dbo].exitstatetypes t
ON t.id = s.exitstatetypeid
WHERE s.id = (SELECT Max(es.id)
FROM exitstates es
WHERE es.exitid = x.id)
ORDER BY s.insertdate
Get row numbers, left outer join and set null row number value to -1 (like below, might have to fix it up a bit as I don't have a schema to work with):
;with RowNumber( ExitId, RowNumber )
as
(
SELECT
x.Id
, ROW_NUMBER() OVER (PARTITION BY s.ExitStateTypeId ORDER BY s.InsertDate)
FROM
[DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s
on x.Id = s.ExitId
WHERE
s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
and s.ExitStateTypeId in ( 4, 7 )
)
SELECT
ISNULL( rn.RowNumber, -1 ) AS Number
,x.Id
,p.FirstName
,p.LastName
,p.PN
,t.Name
,s.ExitStateTypeId as [Status]
,g.Name
,x.OrganisationId
,d.Name AS Direction
,d.Id AS DirectionId
,h.Name AS Referal
,h.Id AS HealthOrgTypeId
,s.IssueDate
,s.InsertDate
FROM [DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s on x.Id = s.ExitId
INNER JOIN [DB1].[dbo].[HealthOrgTypes] h on x.HealthOrgTypeId = h.Id
INNER JOIN [DB1].[dbo].[Directions] d on x.DirectionId = d.Id
INNER JOIN [DB1].[dbo].[HealthCards] c on x.HealthCardId = c.Id
INNER JOIN [DB2].[pr].[TABLE] p on p.Id = c.TABLEId
INNER JOIN [DB3].[orgs].[Organizations] g on g.Id = x.OrganisationId
INNER JOIN [DB4].[dbo].ExitStateTypes t on t.Id = s.ExitStateTypeId
left outer join RowNumber rn
on x.Id = rn.ExitId
WHERE s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
ORDER BY s.InsertDate