How can we access nested object using n1ql by applying filter to object name - couchbase

Sample JSON:
{
"id":"idValue",
"rank":{
"1":{
"city":"Mumbai"
},
"2":{
"city":"Delhi"
}
},
"KEY":"RANK"
}
Expected result: get the document max rank city where "KEY"="RANK"
[
{
"id":"idValue",
"city":"Delhi"
}
]
Query:
SELECT
b.id,
(SELECT p.val
FROM OBJECT_PAIRS(b.rank) p
WHERE `p`.`name` = (SELECT to_string(MAX(TONUMBER(v)))
FROM OBJECT_NAMES(b.rank) v))
FROM
`rating` b
WHERE
b.KEY = 'RANK'

SELECT b.id,
(SELECT RAW MAX([TONUMBER(op.name) , op.val])[1]
FROM OBJECT_PAIRS(b.`rank`) AS op)[0].*
FROM mybucket AS b
WHERE b.`KEY` = "RANK";
OR
SELECT b.id, b.`rank`.[name].city
FROM mybucket AS b
LET name = TO_STR(ARRAY_MAX(ARRAY TONUMBER(n) FOR n:v IN b.`rank` END))
WHERE b.`KEY` = "RANK";

Related

How to write subquery with join using sequelize in node js?

await a.findAll({
where: {status: 1},
include: [
{
model: b,
association: b.hasOne(a,{foreignKey:'a_id',as:"childData"}),
where: {
status: 1,
},
required: false,
},
],
});
I got this query using the above sequelize method.
select * from a inner join b on a.id=b.a_id where a.status=1, b.status=1
But I want a query like this. Both a subquery and the Join method must be used. So how can I do it?
(select * from a where status=1) X inner join (select * from b where status=1) Y ON X.id=Y.a_id

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.

Is there any way to build a JSON that looks like this using SQL Server 2019?

I have this SQL Query:
SELECT
c.customer_name as name,
c.customer_ssn as social_number,
c.telephone as telephone,
c.email as email,
u.user_name as name
FROM
Customer c
LEFT OUTER JOIN
User u ON c.id_customer = u.id_customer
WHERE
c.id_customer = 2
FOR JSON PATH
SELECT * FROM Customer WHERE ID_CUSTOMER = 2
SELECT * FROM User WHERE ID_Customer = 2
This query returns this JSON :
[
{
"name": "blablabla",
"social": "123123123",
"telephone": "91123123",
"email": "blabla#gmail.com",
"name":"blabla"
}
]
Is there any way to get a JSON that looks like this:
{
"name": "blabla",
"social_number": "123123123",
"emails": [
{
"email": "blabla#gmail.com"
},
{
"email": "blablabla#gmail.com"
}
],
"telephones": [
{
"number": "(604)6622141"
},
{
"number": "(652) 2123223"
}
],
Thank you for the help!
I'm still new to coding and StackOverflow... sorry for any mistakes!
You can use correlated subqueries, with FOR JSON in each one
SELECT
c.customer_name as name,
c.customer_ssn as social_number,
telephones = (
SELECT telephone
FROM telephone t
WHERE t.id_customer = c.id_customer
FOR JSON PATH
),
emails = (
SELECT email
FROM email e
WHERE e.id_customer = c.id_customer
FOR JSON PATH
),
u.user_name as name
FROM
Customer c
LEFT OUTER JOIN
User u ON c.id_customer = u.id_customer
WHERE
c.id_customer = 2
FOR JSON PATH;
You can also do this as an APPLY
SELECT
c.customer_name as name,
c.customer_ssn as social_number,
t.telephones,
e.emails,
u.user_name as name
FROM
Customer c
LEFT OUTER JOIN
User u ON c.id_customer = u.id_customer
OUTER APPLY (
SELECT telephone
FROM telephone t
WHERE t.id_customer = c.id_customer
FOR JSON PATH
) t(telephones)
OUTER APPLY (
SELECT email
FROM email e
WHERE e.id_customer = c.id_customer
FOR JSON PATH
) e(emails)
WHERE
c.id_customer = 2
FOR JSON PATH;

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.

SQL GROUP_CONCAT not working with 2 table join

I have this query which is working as expected:
Query
SELECT name, date, enddate, abo_name, bill_id
FROM (
SELECT CONCAT(c.firstname, " ", c.surname) AS name, GROUP_CONCAT(b.date) AS date, GROUP_CONCAT(b.endDate) AS enddate, GROUP_CONCAT(b.abo_id) AS abo_name, GROUP_CONCAT(b.id) AS bill_id
FROM customer c
LEFT JOIN bill b ON c.id = b.customer_id
GROUP BY name
) t
Output (JSON)
{
name: "Max Mustermann",
date: "2018-09-13,2018-09-27",
enddate: "2018-09-13,2018-09-28",
abo_name: "1,2",
bill_id: "23,27"
},
...
But now I need to add more detailed information to the abo_name property, I need to output the full abo name. I tried to just add an INNER JOIN to the query, but then the GROUP_CONCAT doesn't work anymore.
Here's the example:
Query
SELECT name, date, enddate, abo_name, bill_id
FROM (
SELECT CONCAT(c.firstname, " ", c.surname) AS name, GROUP_CONCAT(b.date) AS date, GROUP_CONCAT(b.endDate) AS enddate, GROUP_CONCAT(a.name) AS abo_name, GROUP_CONCAT(b.id) AS bill_id
FROM customer c
LEFT JOIN bill b ON c.id = b.customer_id
INNER JOIN abo a ON b.abo_id = a.id
GROUP BY name
) t
Output (JSON)
{
name: "Max Mustermann",
date: "2018-09-13",
enddate: "2018-09-13",
abo_name: "Einzelstunde",
bill_id: "23"
},
{
name: "Max Mustermann",
date: "2018-09-27",
enddate: "2018-09-28",
abo_name: "Schnupperstunde",
bill_id: "27"
},
As you can see the data doesn't concat and 2 objects are created. Does anybody have an idea why this is the case?
Thank you for your time and help!
abo has a column named name. Aggregate by the expression or use a different alias:
SELECT CONCAT(c.firstname, ' ', c.surname) AS new_name, GROUP_CONCAT(b.date) AS date, GROUP_CONCAT(b.endDate) AS enddate, GROUP_CONCAT(a.name) AS abo_name, GROUP_CONCAT(b.id) AS bill_id
FROM customer c LEFT JOIN
bill b
ON c.id = b.customer_id INNER JOIN
abo a
ON b.abo_id = a.id
GROUP BY new_name