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

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

Related

Sequelize SubQueries generate wrong SQL with joins

We are generating SQL Query with sequelize. Below is the code sample. We already have tries all possible ways like nest: true, distinct: true, raw: true But none of the things work to generate the correct sql
Associations:
db.MeasurementVersions.belongsTo(db.Measurements, {
foreignKey: 'measurementId',
sourceKey: 'id',
as: 'measurementDetails',
});
db.MeasurementVersions.hasMany(db.MeasurementVersions, {
foreignKey: 'measurementId',
sourceKey: 'measurementId',
as: 'measurementVersionsGrouped',
});
db.Measurements.hasMany(db.TakeoffHasMeasurements, {
foreignKey: 'measurementId',
sourceKey: 'id',
});
db.TakeoffHasMeasurements.hasMany(db.TakeoffHasMeasurements, {
foreignKey: 'measurementId',
sourceKey: 'measurementId',
as: 'TakeoffHasMeasurementsMeasurementRightSelfJoin',
});
Sequelize Code
db.MeasurementVersions.findAll({
subQuery: true,
attributes: [[fn('MAX', col(`${db.MeasurementVersions.tableName}.modifiedDate`)), 'MaxTime']],
include: [
{
model: db.MeasurementVersions,
where: {
modifiedDate: { [Operator.eq]: col(`${db.MeasurementVersions.tableName}.MaxTime`) },
status: 'active',
},
as: 'measurementVersionsGrouped',
},
{
attributes: [['quantity', 'quantity'], 'estimateId', 'fileVersionId'],
model: db.Measurements,
as: 'measurementDetails',
required: true,
where: { estimateId },
include: [
{
model: db.TakeoffHasMeasurements,
subQuery: true,
attributes: [[fn('MAX', col(`${db.TakeoffHasMeasurements.tableName}.updatedDate`)), 'MaxTime5']],
include: [
{
model: db.TakeoffHasMeasurements,
as: 'TakeoffHasMeasurementsMeasurementRightSelfJoin',
where: {
updatedDate: { [Operator.eq]: col(`${db.TakeoffHasMeasurements.tableName}.MaxTime5`) },
status: 'active',
},
},
],
},
],
},
],
group: ['measurementId'],
});
The generated SQL query is as below:
SELECT *
FROM
(SELECT
`measurementVersions`.`id`,
MAX(`measurementVersions`.`modifiedDate`) AS `MaxTime`,
`measurementVersions`.`measurementId`,
`measurementDetails->takeoff_has_measurements`.`id` AS `measurementDetails.takeoff_has_measurements.id`,
MAX(`takeoff_has_measurements`.`updatedDate`) AS `measurementDetails.takeoff_has_measurements.MaxTime5`
FROM
`measurementVersions` AS `measurementVersions`
LEFT OUTER JOIN `takeoff_has_measurements` AS `measurementDetails->takeoff_has_measurements` ON `measurementDetails`.`id` = `measurementDetails->takeoff_has_measurements`.`measurementId`
WHERE
(SELECT
`measurementDetails`.`id`
FROM
`measurements` AS `measurementDetails`
LEFT OUTER JOIN (`takeoff_has_measurements` AS `takeoff_has_measurements`
INNER JOIN `takeoff_has_measurements` AS `takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin` ON `takeoff_has_measurements`.`measurementId` = `takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`measurementId`
AND `takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`updatedDate` = `takeoff_has_measurements`.`MaxTime5`
AND `takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`status` = 'active') ON `measurementDetails`.`id` = `takeoff_has_measurements`.`measurementId`
WHERE
(`measurementDetails`.`estimateId` = 'e861a343-ed44-4af5-b488-758c464f416b'
AND `measurementDetails`.`id` = `measurementVersions`.`measurementId`)
LIMIT 1) IS NOT NULL
GROUP BY `measurementId`) AS `measurementVersions`
INNER JOIN
`measurementVersions` AS `measurementVersionsGrouped` ON `measurementVersions`.`measurementId` = `measurementVersionsGrouped`.`measurementId`
AND `measurementVersionsGrouped`.`modifiedDate` = `measurementVersions`.`MaxTime`
AND `measurementVersionsGrouped`.`status` = 'active'
INNER JOIN
`measurements` AS `measurementDetails` ON `measurementVersions`.`measurementId` = `measurementDetails`.`id`
AND `measurementDetails`.`estimateId` = 'e861a343-ed44-4af5-b488-758c464f416b'
INNER JOIN
`takeoff_has_measurements` AS `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin` ON `measurementDetails.takeoff_has_measurements.measurementId` = `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`measurementId`
AND `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`updatedDate` = `takeoff_has_measurements`.`MaxTime5`
AND `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`status` = 'active'
But the expected SQL Query we need is as below(denoted with **):
SELECT *
FROM
(SELECT
`measurementVersions`.`id`,
MAX(`measurementVersions`.`modifiedDate`) AS `MaxTime`,
`measurementVersions`.`measurementId`
FROM
`measurementVersions` AS `measurementVersions`
GROUP BY `measurementId`) AS `measurementVersions`
INNER JOIN
`measurementVersions` AS `measurementVersionsGrouped` ON `measurementVersions`.`measurementId` = `measurementVersionsGrouped`.`measurementId`
AND `measurementVersionsGrouped`.`modifiedDate` = `measurementVersions`.`MaxTime`
AND `measurementVersionsGrouped`.`status` = 'active'
INNER JOIN
`measurements` AS `measurementDetails` ON `measurementVersions`.`measurementId` = `measurementDetails`.`id`
AND `measurementDetails`.`estimateId` = 'e861a343-ed44-4af5-b488-758c464f416b'
LEFT OUTER JOIN (`takeoff_has_measurements` AS `measurementDetails->takeoff_has_measurements`
INNER JOIN **( select MAX(`takeoff_has_measurements`.`updatedDate`) from `takeoff_has_measurements` AS `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`
ON `measurementDetails->takeoff_has_measurements`.`measurementId` = `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`measurementId`
AND `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`updatedDate` = `takeoff_has_measurements`.`MaxTime5`
AND `measurementDetails->takeoff_has_measurements->TakeoffHasMeasurementsMeasurementRightSelfJoin`.`status` = 'active')**)
ON `measurementDetails`.`id` = `measurementDetails->takeoff_has_measurements`.`measurementId`
It should generate the correct sql

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

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

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 can i get data in one array using JSON_ARRAYAGG and JSON_OBJECT in SQL query?

This is my query, i'm using JSON_ARRAYAGG and JSON_OBJECT for hierarchy relations, but my concern is that i want data in following formated data. Don't be confuse with joins just help me get the data i want.
SELECT
CU.contact_group_id,
JSON_ARRAYAGG(
JSON_OBJECT('contact_user', users.user)
) AS `contact_users`
FROM
contact_user as CU
INNER JOIN (
SELECT
U.id,
JSON_ARRAYAGG(
JSON_OBJECT('id', U.id, 'user', U.first_name)
) as `user`
FROM
users as U
) as `users` on CU.user_id = users.id
Data i get:
"users": [
{
"contact_user": [
{
"id": 1,
"user": "dash"
},
{
"id": 3,
"user": "dash1"
}
]
}
]
Data i want:
"users": [
{
"id": 1,
"user": "dash"
},
{
"id": 3,
"user": "dash1"
}
]
Test this:
SELECT JSON_OBJECT('users', JSON_ARRAYAGG(JSON_OBJECT('id', users.id, 'user', users.first_name))) AS `users`
FROM users
-- check if the following line is really needed
-- INNER JOIN contact_user on contact_user.user_id = users.id
SELECT
CU.contact_group_id,
users.user AS `contact_users`
FROM
contact_user as CU
INNER JOIN (
SELECT
U.id,
JSON_ARRAYAGG(
JSON_OBJECT('id', U.id, 'user', U.first_name)
) as `user`
FROM
users as U
) as `users` on CU.user_id = users.id

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.