Add select COUNT events in common between the current user and the others in DQL query - postgresql

I have this DQL query in Symfony 4 project, it does select all users who are registered in all the same events as current user
$query = $this->_em->createQuery(
"select u as user, er.dateRegistration from App:EventRegistration er
left join App:User u with er.user = u.id
where er.user != :user_id and
er.event in (select identity(er2.event) from App:EventRegistration er2
where er2.user = :user_id)")
->setParameter('user_id', $user->getId());
return $query->getResult();
Now, in the same query, I'd like to select COUNT how many times each one of the other users has registered in the same event of the current user.
I mean the number of events in common between the current user and the others.
if I add count(er.id) to the select
select u as user, er.dateRegistration, count(er.id)
I get this error :
SQLSTATE[42803]: Grouping error: 7 ERREUR: la colonne « u0_.username » doit apparaître dans la clause GROUP BY ou doit être utilisé dans une fonction d'agrégat
LINE 1: SELECT u0_.username AS username_0, u0_.username_canonical AS..

You need to add group by;
$query = $this->_em->createQuery(
"select u as user, count(er.id) as register_count from App:EventRegistration er
left join App:User u with er.user = u.id
where er.user != :user_id and
er.event in (select identity(er2.event) from App:EventRegistration er2
where er2.user = :user_id) group by u.id")
->setParameter('user_id', $user->getId());
return $query->getResult();
It will give you register count of each user but in this case you can not expose the "er.dateRegistration" because now you are grouping counts for every user.

Related

Moodle SQL report

I am trying to make an SQL report. In this reports there would be "Duplicated users", "Special users", "Test users" and "Normal users". There is a checkbox for users (only the administrator sees this checkbox) and if the admin ticks this chechkbox the user will be a "Duplicated user", special users will be those who have xy.com in their email addresses and test users will be those who have the word "test" in their firstnames and all the other users will be normal users. My problem is if a user is a duplicated user then they appear twice in this report, I think I know why but I don't know how to solve it, they appear once as normal users and once as duplicated user but I only want them to appear as duplicated users, here is my code:
SELECT distinct(u.email), u.username, u.lastname, if(DATE_FORMAT(FROM_UNIXTIME(u.firstaccess),'%Y-%m-%d') = '1970-01-01', 'Never logged in', DATE_FORMAT(FROM_UNIXTIME(u.firstaccess),'%Y-%m-%d')) AS 'First log in', u.firstname,
CASE
WHEN uif.shortname = 'duplicated' and uid.data = 1 THEN 'Duplicated user'
WHEN u.firstname like '%test%' THEN 'Test user'
WHEN u.email like '%#xy.com%' THEN 'Special user'
ELSE
'Normal user'
END AS Usertype
FROM prefix_user AS u
JOIN prefix_user_info_data AS uid ON uid.userid = u.id
JOIN prefix_user_info_field AS uif ON uid.fieldid = uif.id
where u.deleted = 0 and u.username <> 'guest'
You might be getting duplicates because there is more than one custom field
Try changing the join to this
LEFT JOIN (
SELECT uid.userid, uid.data
FROM prefix_user_info_data AS uid
JOIN prefix_user_info_field AS uif ON uid.fieldid = uif.id AND uif.shortname = 'duplicated'
) uid ON uid.userid = u.id
and the case to this
WHEN uid.data = '1' THEN 'Duplicated user'

Musicbrainz SQL query to get tracks for release_group

I am using the musicbrainz.org postgresql database, which I have installed locally and have accessed via python.
The database is a list of music artists and associated criteria. Here is the schema :
How can I create a SQL query that outputs all tracks for a release group? I am able to get the proper artist info and releases associated with a specific band but the tracks for the release are wrong using the below query's:
strsql_band = "SELECT artist.id, artist.gid, artist.name, artist.comment FROM artist WHERE artist.name=%s AND type>1 ORDER BY type, artist.last_updated DESC"
strsql_memberid = "SELECT entity0, link.begin_date_year, link.end_date_year FROM l_artist_artist l JOIN link ON l.link=link.id WHERE entity1=%s AND link_type=103"
strsql_release = "SELECT id, release_group.name FROM release_group WHERE artist_credit=%s"
# This does not return the correct tracks for the release
strsql_track = "SELECT id, position, name, length FROM track WHERE artist_credit=%s LIMIT 15"
Any help would be greatly appreciated, I have been banging my head on this for hours now.
medium and track table will give you this information
Here is the query that worked for my case:
SELECT
array_agg(track.name) as track_list,
release.gid as release_gid,
release.release_group as release_group_id
FROM track
INNER JOIN medium
ON track.medium=medium.id
INNER JOIN release
ON medium.release=release.id
GROUP BY release.gid, release.release_group limit 5;
Sample Results
release_gid release_group track_list
00000363-74c9-4c3b-bef7-a433eb9687e3 950559 {"Small Screen",Alice,Dauntless,Lullaby,"Grinding the Mill","Four Colors","2000 Gods","This Life","More Than Meets the Eye","The World"}
00000ba0-d5e2-41d7-9c5d-48e8eb04226a 388941 {"Ai, Vanna","Dod māmiņa, kam dodama","Mēs sūdzēsimies Strazdbūrā","Ar Eiropu plecos","Mīļais mans (Oi ļuļi, oi ļuļi)","Tu tik lūr, monamūr","Kocēni, Dikļi un Tožas","Sev augstu laimi vēlēju","Happy mērsrags","Tur es dzēru, tur man tika","Pritonā pie eglītes","Kur ir manas dāvaniņas","Iespraud svecīti","Ints un Ģirts","Mazs putniņš kājām... (Vai Rīga gatava?)","Melngalvju blūzs",Siergriezējs,"Zeva dziesma","Kentaura skaistumkopšanas salonā","Es sakūru uguntiņu (Gaisā skrēja)","Tu nesit... (Nestandarta žoklis)"}
00000ff3-8918-400f-89d5-ec80f52465bf 530779 {"SING IT","Precious Days",トキメキ}
0000172d-6e43-4d7d-8647-da718593a97a 2382060 {"J'ai besoin d'un doliprane","Cœur brisé","Mon proprio","J'me demande","Extra extra terrestre","Bienvenue chez moi (dans ma coloc)","L'amour c'est du pipeau","La caissière du casino",Jean-Marc,"Toutes des salopes"}

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;

postgresql mathematical formula error

Hi I am trying to use a mathematical function on each row in postgresql.
But It gives me a error.
My Query:
Select
stock_inventory_line.product_code AS Sku,
COUNT(sale_order_line.name) AS Qty_Sold,
stock_inventory_line.product_qty AS Current_Qty,
(stock_inventory_line.product_qty / Qty_Sold) AS NOM
From
sale_order_line,
product_product,
product_template,
product_category,
stock_inventory_line
WHERE
sale_order_line.product_id = product_product.id AND
product_product.product_tmpl_id = product_template.id AND
product_template.categ_id = product_category.id AND
product_product.default_code = stock_inventory_line.product_code
GROUP BY
Sku,
Current_Qty,
NOM;
On this Query It gives me a error: column qty_sold doesn't exist.
If i change the 5th line to
(stock_inventory_line.product_qty / COUNT(sale_order_line.name)) AS NOM
It gives me an error: Aggregate functions not allowed in group by.
You are trying to use COUNT(sale_order_line.name) as a group by item. Aggreagte functions work on grouped item. They are not for grouping them.
I do not know your tables but try
Select
stock_inventory_line.product_code AS Sku,
COUNT(sale_order_line.name) AS Qty_Sold,
stock_inventory_line.product_qty AS Current_Qty,
(stock_inventory_line.product_qty / COUNT(sale_order_line.name)) AS NOM
From
sale_order_line,
product_product,
product_template,
product_category,
stock_inventory_line
WHERE
sale_order_line.product_id = product_product.id AND
product_product.product_tmpl_id = product_template.id AND
product_template.categ_id = product_category.id AND
product_product.default_code = stock_inventory_line.product_code
GROUP BY
stock_inventory_line.product_code,
stock_inventory_line.product_qty;
Basically I remove NOM from the GROUP BY. It is a product for each group, not something you group by.
I run into problems like this all the time. Using a CTE always works for me. Do your aggregations inside the CTE then when you call them in the outer statement, Postgres sees them as numeric instead of aggregations. Your query might run a bit faster too!
Example:
WITH cte AS(
SELECT
sale_order_line.product_id,
stock_inventory_line.product_code,
stock_inventory_line.product_code AS Sku,
COUNT(sale_order_line.name) AS Qty_Sold,
stock_inventory_line.product_qty AS Current_Qty,
(stock_inventory_line.product_qty / Qty_Sold) AS NOM
FROM
sale_order_line,
stock_inventory_line)
SELECT Sku, Qty_Sold, Current_Qty, NOM
FROM
cte,
product_product,
product_template,
product_category
WHERE
cte.product_id = product_product.id AND
product_product.product_tmpl_id = product_template.id AND
product_template.categ_id = product_category.id AND
product_product.default_code = cte.product_code
GROUP BY
Sku,
Current_Qty,
NOM;

Moodle Student list with Groups and Course

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"))