Moodle Student list with Groups and Course - moodle

I am using moodle2.4.6. I want a list of user with their groups and their courses.

You will need to do an SQL query to get this information.
Assuming you are using the default 'mdl_' prefix for tables, you will need to join together the following tables:
mdl_user - the details of the users
mdl_user_enrolments - (user_enrolments.userid = user.id) which course enrolments the user
has
mdl_enrol - (enrol.id = user_enrolments.enrolid) details of which
enrolment instances these are
mdl_course - (course.id = enrol.courseid) details of the courses these users are enroled in
mdl_groups_members - (groups_members.userid = user.id) details of the
groups these users are in
mdl_groups - (groups.id =
groups_members.groupid AND groups.courseid = course.id) name and
description of the groups the user is in (for each course)
Please comment if you need help turning that pseudo code into actual SQL, or if you need help with the Moodle database access API ( http://docs.moodle.org/dev/Data_manipulation_API )

SELECT
mdl_user.username,
mdl_user.firstname,
mdl_user.lastname,
mdl_course.fullname,
mdl_course.idnumber,
mdl_groups_members.groupid,
mdl_groups.name
FROM (mdl_groups_members
INNER JOIN ((mdl_course
INNER JOIN (mdl_user_enrolments
INNER JOIN mdl_enrol ON mdl_user_enrolments.enrolid = mdl_enrol.id)
ON mdl_course.id = mdl_enrol.courseid) INNER JOIN mdl_user ON mdl_user_enrolments.userid = mdl_user.id)
ON mdl_groups_members.userid = mdl_user.id) INNER JOIN mdl_groups
ON (mdl_groups.courseid = mdl_course.id) AND (mdl_groups_members.groupid = mdl_groups.id)
WHERE (((mdl_user.username) = "102993") AND ((mdl_course.category) = "36"))

Related

Linking Assignments to Rubrics in Moodle

Rubrics in Moodle are fine but it's hard to get an overview of all the rubrics used in a course.
I'm trying to write a query that lists all the assignments together with their rubric criteria.
This is my query:
SELECT cou.fullname, ass.name, def.name, cri.description
FROM mdl_course cou
inner join mdl_assign ass on ass.course = cou.id
inner join mdl_course_modules cmod on cmod.course = cou.id
inner join mdl_context ctx on ctx.instanceid = cmod.id
inner join mdl_grading_areas are on are.contextid = ctx.id
inner join mdl_grading_definitions def on def.areaid = are.id
inner join mdl_gradingform_rubric_criteria cri on cri.definitionid = def.id
where cou.fullname like '%rduin%1%'
order by cou.fullname, ass.name, cri.sortorder
It took me about two hours to find the link between Assignments and their grading_definitions, but the query still generates too many records. I guess I have to add another join or relationship, but can't figure out which.
Any help would be appreciated!
I've found the solution: there is a double relationship between (assignments and courses) and coursemoudules:
inner join mdl_course_modules cmod on cmod.course = cou.id and ass.id=cmod.instance

Keycloak - Get all Users mapped to roles

I know keycloak has exposed below api,
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>2.0.0.Final</version>
</dependency>
With complete documentation here. I cannot find the required api here to fetch all users with specific role mapped to them.
Problem Statement - I need to pick all users from keycloak server who have a specific role. I need to send email to all users with role mapped to them.
Based on the documentation it appears to be this API:
GET /{realm}/clients/{id}/roles/{role-name}/users
It is there for a while. In this older version however it was not possible to get more than 100 users this way. It was fixed later and pagination possibility was added.
There is an outstanding feature request asking for this function via the API.
In the meantime if your requirement is once-off you could obtain the user names (or email addresses) by interrogating the database joining KEYCLOAK_ROLE to USER_ROLE_MAPPING to USER_ENTITY
Something like:
SELECT username
FROM keycloak_role kr
JOIN user_role_mapping rm ON kr.id = rm.role_id
JOIN user_entity ue ON rm.user_id = ue.id
WHERE kr.name = 'your_role_name';
This should be now possible with the updated rest endpoint.
Set<UserRepresentation> usersOfRole = realmResource.roles().get(roleName).getRoleUserMembers();
Here is another interesting query, which would also display other useful fields.
SELECT kr_role.REALM_ID 'Realm', cl.CLIENT_ID 'Realm Client',
kr_role.NAME 'Role Name',
kr_role.DESCRIPTION 'Role Description',
user_ent.USERNAME 'Domain ID', user_ent.EMAIL 'Email'
FROM keycloak_role kr_role, user_role_mapping role_map,
user_entity user_ent, client cl
WHERE role_map.USER_ID = user_ent.ID
AND kr_role.ID = role_map.ROLE_ID
AND kr_role.CLIENT = cl.ID
AND cl.REALM_ID = '<realm_name>'
AND cl.CLIENT_ID = '<client_name>'
ORDER BY 1, 2, 3;
If anyone is still searching for a Postgres Query to find information regarding users/roles/groups in keycloak database, I came up with this one lately.
It uses two CTEs to have the groups and roles straight (recursing for groups in groups, because they can nest in arbitrary depth and fetching composite roles with their parents) and a simple UNION for group and direct assignments.
Please note the WHERE clause, where you can limit the realm and different aspects. You can search for
all roles from a specific user (just matching username)
all users, that have a particular role assigned (matching role_name)
everything coming from a specific group (I sometimes use it without the username column in the projection to just see, what roles a group has. Please note the prefix in the group column)
-- flat out GROUPS in GROUPS
WITH RECURSIVE groups AS (
SELECT
g.id,
g.id AS parent_group,
g.name,
g.name AS parent_name,
g.realm_id,
1 AS iter
FROM
keycloak_group g
UNION
SELECT
groups.id,
parents.parent_group,
groups.name,
parents.name,
groups.realm_id,
groups.iter + 1
FROM
groups
INNER JOIN keycloak_group parents ON groups.parent_group = parents.id
),
-- Collect roles and composite roles
roles AS (
SELECT
r.id,
r.name AS role_name,
null AS base_role,
c.client_id
FROM
keycloak_role r
LEFT JOIN client c ON r.client = c.id
UNION
SELECT
r.id,
r2.name,
r.name,
c.client_id
FROM
keycloak_role r
JOIN composite_role cr ON r.id = cr.composite
JOIN keycloak_role r2 ON r2.id = cr.child_role
LEFT JOIN client c ON r.client = c.id
)
SELECT DISTINCT
username,
role_name,
base_role, -- for composite roles
client_id,
source,
realm_name
FROM
(
-- Roles from Groups
SELECT
ue.username,
roles.role_name,
roles.base_role,
roles.client_id,
ue.realm_id,
'group ' || g.name AS source,
realm.name AS realm_name
FROM
user_entity ue
JOIN realm ON ue.realm_id = realm.id
JOIN user_group_membership ugm ON ue.id = ugm.user_id
JOIN groups g ON g.id = ugm.group_id
JOIN group_role_mapping grm ON g.parent_group = grm.group_id
JOIN roles roles ON roles.id = grm.role_id
UNION
-- direct role assignments on User
SELECT
ue.username,
roles.role_name,
roles.base_role,
roles.client_id,
ue.realm_id,
'direct',
realm.name
FROM
user_entity ue
JOIN realm ON ue.realm_id = realm.id
JOIN user_role_mapping urm ON ue.id = urm.user_id
JOIN roles roles ON roles.id = urm.role_id
) AS a
WHERE
realm_name = 'realm_name'
AND (
-- username = 'username'
role_name IN ('roleName')
-- source = 'group GROUPNAME'
)
ORDER BY
username,
role_name
;
This query works from keycloak 9 to 16.1.1 (the last jboss/keycloak version I got from docker hub).
SELECT username,
kr.NAME,
kr.REALM_ID
FROM KEYCLOAK_ROLE kr
JOIN USER_ROLE_MAPPING rm ON kr.id = rm.role_id
JOIN USER_ENTITY ue ON rm.user_id = ue.id
ORDER BY USERNAME,
NAME,
REALM_ID;

How to create variables in derived table using different conditions

I want to generate a table and all the variables I need are from a derived temporary table. Now, I need to calculate the time differences under different conditions, and I need to deal with 2 questions:
1. how to create variables in derived table.
2. how to split a variable into 2 variables using different conditions.
Please note that the sql statement I provide below is the simplified statement and please pay attention to the comments which will help you understand the question.
Thanks in advance for any tips.
Here is the SQL statement:
Select id, name, offline_time, Process_time from
## in the derived table, use the difference of createon in table a and b to calculte the offline_time and Process_time ##
## when {a.id = st.id AND a.activityid = 5008 and a.sessiontype = 7} a.creaton = a.creaton1 ##
## when {b.activityid = 5011} b.creaton = b.creaton1 ##
(select
(UNIX_TIMESTAMP(MAX(a.createdon)) - UNIX_TIMESTAMP(MAX(b.createdon))) as 'Offline_Time',
(UNIX_TIMESTAMP(MAX(a.createdon1)) - UNIX_TIMESTAMP(MAX(b.createdon1))) as 'Process_Time',
q.id,
q.name,
a.sessiontype
FROM tv_sessiontimer st
LEFT JOIN sessionactivity_log a ON (a.id = st.id AND a.activityid in (5004,5008) and a.sessiontype IN (3,4,5,6,7))
LEFT JOIN sessionactivity_log b ON (a.ssessionId = b.sessionId AND a.id = b.id AND b.activityid in (5003,5011))
INNER JOIN tv_offline_request q ON q.id = a.sessionid
LEFT JOIN tv_subject sub ON (sub.id = q.subjectid AND sub.SortKey > 10800 AND sub.sortkey < 30200)
)

SQL query that joins results created by a query

I have two tables:
TWMWR and TWMWRemark. I have two competing criteria so I am trying to run the query separately and then join them. I am trying to find all the records in TWMWR that meet the following criteria:
PSWMS.TWMREMARK.TXT_REMARK LIKE '%Essential Equipment: N%'
AND PSWMS.TWMREMARK.TP_REMARK = '%CIS%'
then I want to take the list of WR (the records) and join that with another table to find the records that meet the following criteria:
PSWMS.TWMREMARK.ID_OPER = 'IXM0Q74'
AND PSWMS.TWMREMARK.TP_REMARK = 'CLM'
AND PSWMS.TWMREMARK.TXT_REMARK LIKE '%SOC%'
They have to be done separately. Can anyone help? I have pasted what I have tried below. I am using mySql developer.
SELECT PSWMS.TWMWR.CD_WR,
PSWMS.TWMWR.TP_JOB,
PSWMS.TWMWR.TS_OPER_RECORDED,
PSWMS.TWMWR.ID_CUSTOMER,
PSWMS.TWMREMARK.TS_REMARK,
PSWMS.TWMREMARK.ID_OPER,
PSWMS.TWMREMARK.TP_REMARK AS TP_REMARK1,
PSWMS.TWMREMARK.TXT_REMARK
FROM PSWMS.TWMWR
INNER JOIN PSWMS.TWMREMARK
ON PSWMS.TWMWR.CD_WR = PSWMS.TWMREMARK.CD_WR
WHERE PSWMS.TWMWR.TP_JOB = 'CLMDPD'
AND PSWMS.TWMWR.TS_OPER_RECORDED >= '21, Oct 2013'
AND PSWMS.TWMREMARK.ID_OPER = 'IXM0Q74'
AND PSWMS.TWMREMARK.TP_REMARK = 'CLM'
AND PSWMS.TWMREMARK.TXT_REMARK LIKE '%SOC%'
GROUP BY PSWMS.TWMWR.CD_WR,
PSWMS.TWMWR.TP_JOB,
PSWMS.TWMWR.TS_OPER_RECORDED,
PSWMS.TWMWR.ID_CUSTOMER,
PSWMS.TWMREMARK.TS_REMARK,
PSWMS.TWMREMARK.ID_OPER,
PSWMS.TWMREMARK.TP_REMARK,
PSWMS.TWMREMARK.TXT_REMARK
INNER JOIN
SELECT PSWMS.TWMWR.CD_WR
FROM PSWMS.TWMWR
INNER JOIN PSWMS.TWMREMARK
ON PSWMS.TWMWR.CD_WR = PSWMS.TWMREMARK.CD_WR
WHERE PSWMS.TWMWR.TP_JOB = 'CLMDPD'
AND PSWMS.TWMWR.TS_OPER_RECORDED >= '21, Oct 2013'
AND PSWMS.TWMREMARK.TXT_REMARK LIKE '%Essential Equipment: N%'
AND PSWMS.TWMREMARK.TP_REMARK = '%CIS%' AS WR
ON PSWMS.TWMWR.CD_WR = WR.CD_WR, PSWMS.TWMREMARK.CD_WR = WR.CD_WR

Querydsl - How use group by and sum

I'd like to do a query than in sql it's:
SELECT users.id, SUM(total), SUM(total*price) FROM sales INNER JOIN users ON sales.id_user=users.id GROUP BY users.id
I tried searching for the solution, but the closest I get was:
QSales sales = QSales.sales;
JPAQuery query = from(sales);
QUsers users = QUsers.users;
query.innerJoin(sales.users, users);
List<Object[]> response = query.groupBy(sales.user).list(sales.user, sales.total.sum());
but i don't know how to get this:
SUM(total*price)
SUM(total*price)
can be expressed as
total.multiply(price).sum()
you can use NumberExpression
NumberExpression totalPrice = sales.total.multiply(sales.price);
then use totalPrice.sum()