adding condition to mysql json query - mysql

I have a simple query like this that go over my mysql records of certain table and gives me jsons out of each record:
SELECT json_object(
'personId', p.id,
'formalName', p.name,
'country', p.country)
FROM person p;
but I formalName can be null, and I wanted to add a condition like
if p.name is null 'NoName' else p.name
is it possible?

Yeap change p.name to case when p.name is null then 'NoName' else p.name end at the end your query will be:
SELECT json_object(
'personId', p.id,
'formalName', case when p.name is null then 'NoName' else p.name end,
'country', p.country)
FROM person p;

Related

Getting NULL value while preparing an array of objects using mysql [duplicate]

I have a json query that gives me json of a joined table of person and pets:
SELECT json_object(
'personId', p.id,
'pets', json_arrayagg(json_object(
'petId', pt.id,
'petName', pt.name
))
)
FROM person p LEFT JOIN pets pt
ON p.id = pt.person_id
GROUP BY p.id;
my issue is that person can have 0 or more pets, and when a person have 0 pets I get list with 1 empty pet, and what I would like to get in that case is empty list.
this is what I get:
{
"personId": 1,
"pets": [
{
"petId": null,
"petName": ""
}
]
}
and I need:
{
"personId": 1,
"pets": []
}
is that possible?
The problem is that LEFT JOIN still returns columns from the table you're joining with, it just sets their values to NULL.
You can use IF to test COUNT(pt.id), as this won't count null values.
SELECT json_object(
'personId', p.id,
'pets', IF(COUNT(pt.id) = 0, JSON_ARRAY(),
json_arrayagg(json_object(
'petId', pt.id,
'petName', pt.name
)
))
)
FROM person p LEFT JOIN pets pt
ON p.id = pt.person_id
GROUP BY p.id;
Another possibility is to put the aggregation in a correlated subquery and use coalesce() to replace it with an empty array if no rows exist.
SELECT json_object('personID', p.id,
'pets', coalesce((SELECT json_arrayagg(json_object('petId', t.id,
'petName', t.name))
FROM pets t
WHERE t.person_id = p.id),
json_array()))
FROM person p;
Adding another option:
select IFNULL( /*expression of select ...JSON_ARRAYAGG(
JSON_OBJECT(....*/,JSON_ARRAY()) jarrayaggAlias
Cleaner below:
IFNULL( expression, ,JSON_ARRAY()) jarrayaggAlias
Result:
/* { jarrayaggAlias: [] }*/
If you swap alt_value for IFNULL to select [], then all your results will be stringyfied.

How to skip NULL values from MySQL CONCAT and GROUP_CONCAT

I have this query that returns the name of the product and the array of images as a JSON string. However, when there is no image attached to a product, I would like this query to return an empty array for the images property.
Currently, it returns this when there is no product image found:
{ "name": "Product Name", "images": [{"id": null, "slug": null}]}
I tried to add an IF condition into the CONCAT method, but it returns the same response.
SELECT p.name,
CONCAT('[',
IF(i.id = NULL,
'',
GROUP_CONCAT(DISTINCT (
JSON_OBJECT(
'id', i.id,
'slug', i.slug
)
))
),
']') AS images
FROM products AS p
LEFT JOIN _product_images AS pi ON pi.pId = p.id
LEFT JOIN images AS i ON i.id = pi.iId
WHERE p.id = 4;
Thank you!
As other have mentioned, i.id = NULL will always evaluate to NULL. But your approach is needlessly complicated and would raise an error on a strictly configured server. On db-fiddle I get the following error:
ER_MIX_OF_GROUP_FUNC_AND_FIELDS: In aggregated query without GROUP BY,
expression #2 of SELECT list contains nonaggregated column
'test.i.id'; this is incompatible with sql_mode=only_full_group_by
demo
So the check i.id IS NULL needs to be done within the GROUP_CONCAT() function:
SELECT p.name,
CONCAT('[',
GROUP_CONCAT(DISTINCT (
IF (i.id IS NULL, '',
JSON_OBJECT(
'id', i.id,
'slug', i.slug
)
)
)),
']') AS images
FROM products AS p
LEFT JOIN _product_images AS pi ON pi.pId = p.id
LEFT JOIN images AS i ON i.id = pi.iId
WHERE p.id = 4
However - You can avoid the check, when you use an INNER JOIN. But the INNER JOIN will also ignore the data from the products table - So I would do that JOIN in a correlated subquery. An finally you can use JSON_ARRAYAGG() to generate a JSON array.
demo
SELECT p.name, COALESCE((
SELECT JSON_ARRAYAGG(JSON_OBJECT(
'id', i.id,
'slug', i.slug
))
FROM _product_images AS pi
JOIN images AS i ON i.id = pi.iId
WHERE pi.pId = p.id
), JSON_ARRAY()) AS images
FROM products AS p
#WHERE p.id = 4;
demo
You should be using IS NULL to check for a NULL value:
SELECT
p.name,
CONCAT('[',
GROUP_CONCAT(
IF(id IS NULL,
'',
DISTINCT JSON_OBJECT('id', i.id, 'slug', i.slug))),
']') AS images
FROM products AS p
LEFT JOIN _product_images AS pi ON pi.pId = p.id
LEFT JOIN images AS i ON i.id = pi.iId
WHERE p.id = 4
GROUP BY p.name;
As a side note, DISTINCT is not a function, and you should not be using it as such, so I removed the function parentheses which you were using.
Edit: Updated SQL to satisfy the group restrictions. The IF-Statement for checking i.id outside of the GROUP_CONCAT would fail, due to multiple image items per row.
IF(i.id = NULL, ...) returns NULL, for whatever value has i.id (even NULL), which is a falsy value.
You want to use instead IF (i.id IS NULL, ...)
From documentation :
You cannot use arithmetic comparison operators such as =, <, or <> to test for NULL. To demonstrate this for yourself, try the following query:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+

add condition to mysql json_arrayagg function

I have a json query that gives me json of a joined table of person and pets:
SELECT json_object(
'personId', p.id,
'pets', json_arrayagg(json_object(
'petId', pt.id,
'petName', pt.name
))
)
FROM person p LEFT JOIN pets pt
ON p.id = pt.person_id
GROUP BY p.id;
my issue is that person can have 0 or more pets, and when a person have 0 pets I get list with 1 empty pet, and what I would like to get in that case is empty list.
this is what I get:
{
"personId": 1,
"pets": [
{
"petId": null,
"petName": ""
}
]
}
and I need:
{
"personId": 1,
"pets": []
}
is that possible?
The problem is that LEFT JOIN still returns columns from the table you're joining with, it just sets their values to NULL.
You can use IF to test COUNT(pt.id), as this won't count null values.
SELECT json_object(
'personId', p.id,
'pets', IF(COUNT(pt.id) = 0, JSON_ARRAY(),
json_arrayagg(json_object(
'petId', pt.id,
'petName', pt.name
)
))
)
FROM person p LEFT JOIN pets pt
ON p.id = pt.person_id
GROUP BY p.id;
Another possibility is to put the aggregation in a correlated subquery and use coalesce() to replace it with an empty array if no rows exist.
SELECT json_object('personID', p.id,
'pets', coalesce((SELECT json_arrayagg(json_object('petId', t.id,
'petName', t.name))
FROM pets t
WHERE t.person_id = p.id),
json_array()))
FROM person p;
Adding another option:
select IFNULL( /*expression of select ...JSON_ARRAYAGG(
JSON_OBJECT(....*/,JSON_ARRAY()) jarrayaggAlias
Cleaner below:
IFNULL( expression, ,JSON_ARRAY()) jarrayaggAlias
Result:
/* { jarrayaggAlias: [] }*/
If you swap alt_value for IFNULL to select [], then all your results will be stringyfied.

MySQL COUNT() to return 0

I have a query that looks like this:
SELECT
app.application_id,
j.job_number,
j.job_id,
j.job_title,
j.job_city,
j.job_state,
p.person_id AS candidate_id,
p.first_name,
p.last_name,
app.start_date,
ope1.percent_complete,
MAX(CASE
WHEN r.role_display_name = 'ENG - Recruiter' THEN
(SELECT CASE WHEN COUNT(last_name) = 0 THEN
'Unassigned'
ELSE
COUNT(last_name)
END AS uname
FROM users
JOIN job_roles ON job_roles.user_id = users.user_id
WHERE job_id = j.job_id
AND role_id = r.role_id
)
ELSE '' END) AS role_3
My problem is that COUNT(last_name) will not return 0, because there are no records returned, so there is no value of NULL. All makes sense, however I have tried wrapping it in IFNULL(), ISNULL() and none of them seem to fix this problem. How can I get it to return 0 when there are no records? Do I need another subquery inside the COUNT() aggregate? I would really like to not use another subquery....
If understand correctly what you want you can try to rewrite it this way
SELECT ...
,MAX(CASE WHEN r.role_display_name = 'ENG - Recruiter'
THEN COALESCE(NULLIF(
(
SELECT COUNT(last_name)
FROM users JOIN job_roles
ON job_roles.user_id = users.user_id
WHERE job_id = j.job_id
AND role_id = r.role_id
), 0), 'Unassigned')
ELSE ''
END) as role_3
...

Getting all the records from Patient entity with primary insurance of the patient can be 'P' that is primary

I want the following SQL query in JQPL syntax:
select P.*,PIN.INSURANCE_COMPANY_ID
from PATIENT_INSURANCE PIN
right join PATIENT P ON (PIN.Patient_ID = P.ID
and PIN.INSURANCE_TYPE = 'P' AND PIN.STATUS = 'A')
where P.STATUS = 'A'
Please help.
Try this:
select
p.id,
p.lastName,
p.firstName,
p.middleName,
p.dob,
p.sex,
p.ssn,
p.phone,
p.status,
pi.insuranceCompanyId ,
IF(pi.insuranceType ='P' , 'is P', 'is not P')
from
PatientInsurance pi
right join Patient p
on pi.patientID = p.id
Or if you want all the records that have pi.insuranceType ='P' you can append to the query :
WHERE pi.insuranceType ='P'