How can inner join like this can be converted Sequelize? - sql

I'm primarily trying to see how would you perform inner join here.
SELECT * From "Users" as biz
INNER JOIN "Deals" as d
ON biz.id = d."UserId"
WHERE (biz.latitude BETWEEN 18 AND 21)
AND (biz.longitude BETWEEN -78 AND -73);
this is what I got from documentation... but not sure how to proceed further
Deals.find({ where: { }, include: [User]})

For inner join all you need is required : true :
Deals.find({
where: { },
include: [{
model : User ,
required : true // This will make your inner join
}]})
NOTE : Use findAll or findOne instead of just find

Related

Sequelize - Subselect association to filter parent model

I've recently started to use Sequelize 6. Currently trying to express the following query unsuccessfully.
SELECT u.*
FROM users u
JOIN requests r
ON u.id = r.user_id
WHERE (r.status = true AND r.created_at IN (SELECT
MAX(r.created_at)
FROM users u
INNER JOIN requests r ON r.user_id = u.id
GROUP BY u.id))
GROUP BY u.id, r.id
What I have tried so far:
const result = await User.findAll({
offset: page,
subQuery: false,
limit: rowsPerPage,
where: {
'$requests.status$': true,
},
include: [{
as: 'requests',
model: Request,
separate: true,
required: true,
order: [['createdAt', 'desc']],
limit: 1, // problem is here -> error: missing FROM-clause entry for table "requests"
}],
});
In other words, I'm trying to load the parent model only when the association's status value is true on the last record, and return each individual user row alongside with its latest association.
Regarding the limit problem on my comment, this thread might be useful
https://github.com/sequelize/sequelize/issues/11617
I had to change original SQL a little bit to work with Sequelize because a certain combination of required, where didn't work well.
So, I went off from your description.
I'm trying to load the parent model only when the association's status
value is true on the last record
If I understand this correctly, I think you can use having query to achieve this.
const result = await User.findAll({
offset: page,
subQuery: false,
limit: rowsPerPage,
include: [{
as: 'requests',
model: Request,
required: true
}],
having: {
'$requests.createdAt$': [sequelize.fn('MAX', sequelize.col('`requests`.`createdAt`'))],
'$requests.status$': true
},
group: ['users.id'],
});
This will produce a following SQL. Please try this SQL and let me know if this is what you are looking for or not.
SELECT ... FROM `users` AS `users`
INNER JOIN `requests` AS `requests`
ON `users`.`id` = `requests`.`userId`
GROUP BY `users`.`id`
HAVING `requests`.`createdAt` IN (MAX(`requests`.`createdAt`)) AND `requests`.`status` = 1
LIMIT 0, 5;

Sequelize nested include with required: true generates invalid join

I apologise for the lengthy post in advance!
I am trying to use sequelize in nodeJs to query a Wordpress mysql database with a required: true in a nested include.
However, the generated query includes a bad join (I'd expect the join to be nested like the nested where clause). I don't seem to be able to figure out if I've configured my schema incorrectly or whether I am just doing something else silly.
Any help would be greatly appreciated!
In essence, my schema is:
const Post = sequelize.define('wp_posts', {
ID: {
type: DataType.BIGINT,
primaryKey: true
}
});
const TermRelationship = sequelize.define('wp_term_relationships', {
object_id: {
type: DataType.BIGINT,
primaryKey: true,
allowNull: false
},
term_taxonomy_id: {
type: DataType.BIGINT,
primaryKey: true,
allowNull: false
}
});
const TermTaxonomy = sequelize.define('wp_term_taxonomy', {
term_taxonomy_id: {
type: DataType.BIGINT,
primaryKey: true
}
});
const Term = sequelize.define('wp_terms', {
term_id: {
type: DataType.BIGINT,
primaryKey: true
}
});
The relationships I have defined are:
Post.belongsToMany(TermTaxonomy, {
through: TermRelationship,
otherKey: 'term_taxonomy_id',
foreignKey: 'object_id',
as: 'termTaxonomies'
});
TermTaxonomy.belongsTo(Term, {
foreignKey: 'term_id',
as: 'term'
});
The query I am executing is
const query = {
limit: 1,
include: [
{
model: TermTaxonomy,
required: true,
as: 'termTaxonomies',
include: [
{
model: Term,
as: 'term',
required: true,
}
]
}
]
};
However, the generated query includes a bad join. Here is the generated query. I have included comments where I see the errors:
SELECT
`wp_posts`.*,
`termTaxonomies`.`term_taxonomy_id` AS `termTaxonomies.term_taxonomy_id`,
`termTaxonomies`.`term_id` AS `termTaxonomies.term_id`,
`termTaxonomies`.`taxonomy` AS `termTaxonomies.taxonomy`,
`termTaxonomies`.`description` AS `termTaxonomies.description`,
`termTaxonomies`.`parent` AS `termTaxonomies.parent`,
`termTaxonomies`.`count` AS `termTaxonomies.count`,
`termTaxonomies->wp_term_relationships`.`object_id` AS `termTaxonomies.wp_term_relationships.object_id`,
`termTaxonomies->wp_term_relationships`.`term_taxonomy_id` AS `termTaxonomies.wp_term_relationships.term_taxonomy_id`,
`termTaxonomies->wp_term_relationships`.`term_order` AS `termTaxonomies.wp_term_relationships.term_order`
FROM
(
SELECT
`wp_posts`.`ID`,
`wp_posts`.`post_author`,
`wp_posts`.`post_date_gmt`,
`wp_posts`.`post_content`,
`wp_posts`.`post_title`,
`wp_posts`.`post_excerpt`,
`wp_posts`.`post_status`,
`wp_posts`.`comment_status`,
`wp_posts`.`ping_status`,
`wp_posts`.`post_password`,
`wp_posts`.`post_name`,
`wp_posts`.`to_ping`,
`wp_posts`.`pinged`,
`wp_posts`.`post_modified_gmt`,
`wp_posts`.`post_content_filtered`,
`wp_posts`.`post_parent`,
`wp_posts`.`guid`,
`wp_posts`.`menu_order`,
`wp_posts`.`post_type`,
`wp_posts`.`post_mime_type`,
`wp_posts`.`comment_count`,
-- ERROR
-- wp_terms cannot be joined to wp_posts
`termTaxonomies->term`.`term_id` AS `termTaxonomies.term.term_id`,
`termTaxonomies->term`.`name` AS `termTaxonomies.term.name`,
`termTaxonomies->term`.`slug` AS `termTaxonomies.term.slug`,
`termTaxonomies->term`.`term_group` AS `termTaxonomies.term.term_group`
FROM
`wp_posts` AS `wp_posts`
-- ERROR: bad join!
-- wp_terms cannot be joined to wp_posts
INNER JOIN `wp_terms` AS `termTaxonomies->term` ON `termTaxonomies`.`term_id` = `termTaxonomies->term`.`term_id`
WHERE
(
SELECT
`wp_term_relationships`.`object_id`
FROM
`wp_term_relationships` AS `wp_term_relationships`
INNER JOIN `wp_term_taxonomy` AS `wp_term_taxonomy` ON `wp_term_relationships`.`term_taxonomy_id` = `wp_term_taxonomy`.`term_taxonomy_id`
INNER JOIN `wp_terms` AS `wp_term_taxonomy->term` ON `wp_term_taxonomy`.`term_id` = `wp_term_taxonomy->term`.`term_id`
WHERE
(
`wp_posts`.`ID` = `wp_term_relationships`.`object_id`
)
LIMIT
1
) IS NOT NULL
LIMIT
1
) AS `wp_posts`
INNER JOIN (
`wp_term_relationships` AS `termTaxonomies->wp_term_relationships`
INNER JOIN `wp_term_taxonomy` AS `termTaxonomies` ON `termTaxonomies`.`term_taxonomy_id` = `termTaxonomies->wp_term_relationships`.`term_taxonomy_id`
) ON `wp_posts`.`ID` = `termTaxonomies->wp_term_relationships`.`object_id`;
The error I get is 'Unknown column 'termTaxonomies.term_id' in 'on clause' due to the incorrect join.
The generated query is valid if I either remove required: true or the limit option since it no longer does the strange inner join. However, I just can't seem to get this to work with a required nested include.
FYI: I am using sequelize 4.37.10 with 1.5.3 mysql2 1.5.3.
Thank you very much!
When eager loading, we can force the query to return only those records which have an associated model, effectively converting the query from the default OUTER JOIN to an INNER JOIN. Just remove required:true it will work fine generally this happens when we eager load, probably in your case we are eagerloading.
I hope you find this explanation beneficial.

SQL JSON Help and Query Help needed

Good day Stackoverflow,
I have found myself in a bit of a weird query situation. You see, I have to come up with a stored procedure that returns a data set like so;
[
"TestCase1": {
"SetText": {
"Element":"Username"
"Value":"123456"
},
"SetText": {
"Element":"Username",
"Value":"Admin"
},
"OnClick": {
"Element":"SubmitButton"
},
"Login": {
"Username":"admin",
"Password":"123456"
}
}
]
As you can see the data set is held together by the TestCase1 which is in reference to a Table Column Name. Test.Name
Follow by, the function name holding multiple objects.
Each function has its Keys be the parameter name and the keys values are the parameters values
So in this example, Test Case 1 has 4 actions
SetText("Username", "123456")
SetText("Password", "Admin")
OnClick("SubmitButton")
Login("Admin","123456")
The problem is; the query list below I can't alter it to the way I have the JSON above
SELECT TD.ID, F.[Name] AS [Function], P.[Name] AS [Parameter], E.[Name] AS [Data] FROM [QA].[TestData] TD
LEFT JOIN QA.[Parameter] P ON P.ID = TD.ParameterID
INNER JOIN QA.[Function] F ON F.ID = P.FunctionID
INNER JOIN QA.[XREF_Parameter_Element] XPE ON (P.ParameterTypeID = 1) AND (XPE.ID = TD.DataID)
INNER JOIN QA.[Element] E ON E.ID = XPE.ElementID
UNION ALL
SELECT TD.ID, F.[Name] AS [Function], P.[Name] AS [Parameter], XPV.[Value] AS [Data] FROM [QA].[TestData] TD
LEFT JOIN QA.[Parameter] P ON P.ID = TD.ParameterID
INNER JOIN QA.[Function] F ON F.ID = P.FunctionID
INNER JOIN QA.[XREF_Parameter_Value] XPV ON (P.ParameterTypeID <> 1) AND (XPV.ID = TD.DataID)
ORDER BY TD.ID
FOR JSON PATH, ROOT('TestCase1')
Here is what the query above turns out to be
{
"TestCase1":[
{
"ID":1,
"Function":"SetText",
"Parameter":"Element",
"Data":"Username"
},{
"ID":2,
"Function":"SetText",
"Parameter":"Value",
"Data":"123456"
},{
"ID":3,
"Function":"SetText",
"Parameter":"Element",
"Data":"Username"
},{
"ID":4,
"Function":"SetText",
"Parameter":"Value",
"Data":"Admin"
},{
"ID":5,
"Function":"OnClick",
"Parameter":"Element",
"Data":"SubmitButton"
},{
"ID":6,
"Function":"Login",
"Parameter":"Username",
"Data":"Admin"
},{
"ID":7,
"Function":"Login",
"Parameter":"Password",
"Data":"123456"
}
]
}
Is anyone able to help me out. I am more than willing to share contact information to be more clear. This is just ripping my brain apart.

Is this SQL possible in Sequelize?

I've just started with sequelize and am trying to reproduce the below query.
I have the following Model structure: Review, Entity, ReviewThank
Each Entity can have many Reviews, and each Review can have many ReviewThanks.
An attribute of each review is a 'thumbUp' (boolean) rating.
I'm trying to generate the below query to get a 'thankCount' for each review, along with the Entity rating - thumbUpCount and totalCount - for each Review:
SELECT * FROM (
SELECT COUNT("Review"."id") AS "totalCount", "Review"."EntityId", COUNT(CASE WHEN "Review"."thumbUp" THEN 1 END) AS "thumbUpCount"
FROM "Reviews" AS "Review" GROUP BY "Review"."EntityId"
) AS "EntityRatingTable" LEFT JOIN (
SELECT "Review"."id", "Review"."EntityId", "Review"."uid", "Review"."thumbUp", "Review"."caption", COUNT("ReviewThanks"."id") AS "thankCount"
FROM "Reviews" AS "Review" LEFT OUTER JOIN "ReviewThanks" AS "ReviewThanks" ON "Review"."id" = "ReviewThanks"."ReviewId"
WHERE "Review"."UserId" IN (1) GROUP BY "Review"."id"
) AS "ReviewsTable" ON "ReviewsTable"."EntityId" = "EntityRatingTable"."EntityId";
Is it possible to produce this in sequelize? I've got the "ReviewsTable" query working ok, but unsure how (or if possible) I can join this with the "EntityRatingTable"?
This is what I've got so far:
models.Review.findAll({
attributes: {
include: [
[models.sequelize.fn('COUNT', models.sequelize.col('ReviewThanks.id')), 'thankCount'],
[models.sequelize.fn('COUNT', models.sequelize.col('Review.id')), 'reviewCount'],
],
exclude: ["EntityId", "UserId"],
},
include: [
{
model: models.ReviewThank,
attributes: [],
}, {
model: models.Entity,
}
],
group: ['"Review"."id"', '"Entity.id"'],
})

how can i write this query with mongodb? [duplicate]

This question already has answers here:
How do I perform the SQL Join equivalent in MongoDB?
(19 answers)
Closed 6 years ago.
I want to write this query with mongodb
select *
from tab1 a, tab2 c
where a.a_id = 2
and c.c_id = 3
and a.a_id = c.c_fk_account_id_created_by
I tried this code but didn't get a response:
$cursor = $collection->find(array('$and' => array(array("a_id" => 2), array("c_id" => 3))));
I will assume you have two collections, named tab1 and tab2 in the form of
tab1
{
"_id" : ObjectId("58482a97a5fa273657ace535"),
"a_id" : NumberInt(2)
}
tab2
{
"_id" : ObjectId("58482acca5fa273657ace539"),
"c_id" : NumberInt(3),
"c_fk_account_id_created_by" : NumberInt(2)
}
You will need an aggregation query with two steps, first, $lookup to the second table, and second $match on the proper keys. Like this.
db.tab1.aggregate(
[
{
$lookup: {
"from" : "tab2",
"localField" : "a_id",
"foreignField" : "c_fk_account_id_created_by",
"as" : "c"
}
},
{
$match: {
"a_id": 2,
"c.c_id": 3
}
},
]
);
This will give you an output like this
{
"_id" : ObjectId("58482a97a5fa273657ace535"),
"a_id" : NumberInt(2),
"c" : [
{
"_id" : ObjectId("58482acca5fa273657ace539"),
"c_id" : NumberInt(3),
"c_fk_account_id_created_by" : NumberInt(2)
}
]
}
Good luck!
I wrote an article on just this type of query:
MongoDB Aggregation Framework for T-SQL Pros #3: The $lookup Operator
https://www.linkedin.com/pulse/mongodb-aggregation-framework-t-sql-pros-3-lookup-operator-finch
Essentially you are going to bring all documents from your second table into the results of the first table using the $lookup aggregation operator. You can then use the $match and $group operators to filter and aggregate your data.
It will go something like this:
db.tab1.aggregate([
{ $match:
{ "tab1.a_id": 2 }
},
{ $lookup:
{ from: "tab2",
localField: "a_id",
foreignField: "c_fk_account_id",
as: "tab2_results"
}
},
{ $match:
{ "tab2_results.c_id": 3 }
}
]}
The matching joined documents will be added to the base table's document as an array. It acts as a LEFT join in that null values from the remote table are ignored and your base table document is still returned, only missing remote data.
Hope this helps!
Bill
Let's assume tab1 and tab2 have 3 fields each as a_id, aa1, aa2 and c_id, c_fk_account_id_created_by, cc1
The query will be as follows
db.tab1.aggregate([{$match:{a_id:2}},{$lookup:{from:'tab2', localField:'c_fk_account_id_created_by', foreignField:'a_id', as:'ccArray'}},{$unwind:'$ccArray'},
{$project:{a_id:1,aa1:1, aa2:1, c_id:'$ccArray.c_id',c_fk_account_id_created_by:'$ccArray.c_fk_account_id_created_by',cc1:'$ccArray.cc1'}},{$match:{c_id:3}}])
Explanation of the above query:
As MongoDB doesn't allow to match from second table in the aggregation pipeline so we have to unwind the second table array and compare the value
select *
from tab1 a, tab2 c
where a.a_id = 2 ==> {$match:{a_id:2}}
and c.c_id = 3 ==> (Cannot be done at first so it can be acheived as ) ==> {$unwind:'$ccArray'},
{$project:{a_id:1,aa1:1, aa2:1, c_id:'$ccArray.c_id',c_fk_account_id_created_by:'$ccArray.c_fk_account_id_created_by',cc1:'$ccArray.cc1'}},{$match:{c_id:3}}
and a.a_id = c.c_fk_account_id_created_by ==> {$lookup:{from:'tab2', localField:'c_fk_account_id_created_by', foreignField:'a_id', as:'ccArray'}}