How can I execute this Postgres query in Sequelize? - postgresql

I need to translate this join query into Sequelize. I have associated the three tables involved in the join:
tracks.belongsToMany(tracks_playlists, { foreignKey: 'track_id' });
tracks.belongsToMany(tracks_meta, { foreignKey: 'track_id' });
tracks_meta.belongsToMany(tracks_playlists, { foreignKey: 'track_id'});
Here's the raw query that works:
SELECT tracks_playlists.playlist_id, tracks_playlists.track_id, tracks.track, tracks.track_type, tracks_meta.status, tracks_meta.app_id, tracks_meta.description, tracks_meta.ip
FROM tracks_playlists
INNER JOIN tracks on tracks_playlists.track_id = tracks.track_id
INNER JOIN tracks_meta on tracks.track_id = tracks_meta.track_id
WHERE tracks_playlists.playlist_id = 4;
When I try to run the following code
self.tracks_playlists_table.find({
where: {
playlist_id: 4
},
include: [{
model: self.tracks_table
}]
})
.then(function(resp) {
console.log(resp);
});
it spits out this error:
relation "playlists.trackstracks_playlists" does not exist
This is the query that it generates from my code:
SELECT "TracksPlaylists".*, "Tracks"."track_id" AS "Tracks.track_id",
"Tracks"."track" AS "Tracks.track", "Tracks"."track_type" AS "Tracks.track_type", "Tracks"."created" AS "Tracks.created", "Tracks"."updated" AS "Tracks.updated", "Tracks.trackstracks_playlists"."created" AS "Tracks.trackstracks_playlists.created", "Tracks.trackstracks_playlists"."updated" AS "Tracks.trackstracks_playlists.updated", "Tracks.trackstracks_playlists"."track_id" AS "Tracks.trackstracks_playlists.track_id"
FROM (SELECT "TracksPlaylists"."track_playlist_id", "TracksPlaylists"."track_id", "TracksPlaylists"."playlist_id", "TracksPlaylists"."created", "TracksPlaylists"."updated"
FROM "playlists"."tracks_playlists" AS "TracksPlaylists"
WHERE "TracksPlaylists"."playlist_id" = 4 LIMIT 1) AS "TracksPlaylists"
LEFT OUTER JOIN ("playlists"."trackstracks_playlists" AS "Tracks.trackstracks_playlists"
INNER JOIN "playlists"."tracks" AS "Tracks"
ON "Tracks"."track_id" = "Tracks.trackstracks_playlists"."track_id")
ON "TracksPlaylists"."track_playlist_id" = "Tracks.trackstracks_playlists"."track_id";
Why is it creating the column "trackstracks_playlists"?

Related

Fetching distinct rows from multiple includes with sequelize

I have some nested joins below. I am trying to fetch distinct rows out of it.
Product.findAll({
attributes:[sequelize.fn('DISTINCT', sequelize.col('product.id')), 'product.id']],
include: {
model: Course,
attributes: [],
required: true,
include: {
model: Class,
where: {
classId: args.classId
},
attributes: []
}
}
})
syntax error at or near "DISTINCT"
Query being produced by sequelize,
SELECT "product"."id", DISTINCT("product"."id") AS "product.id" FROM "my_schema"."product_groups" AS "product" INNER JOIN "my_schema"."courses" AS "courses" ON "product"."id" = "courses"."product_group_id" INNER JOIN "my_schema"."classes" AS "courses->classes" ON "courses"."id" = "courses->classes"."course_id" AND "courses->classes"."organization_id" = '68700940-f509-4662-975f-a3ba3382aa9b';;
Working sql query,
SELECT DISTINCT("product"."id") FROM "my_schema"."product_groups" AS "product" INNER JOIN "my_schema"."courses" AS "courses" ON "product"."id" = "courses"."product_group_id" INNER JOIN "my_schema"."classes" AS "courses->classes" ON "courses"."id" = "courses->classes"."course_id" AND "courses->classes"."organization_id" = '68700940-f509-4662-975f-a3ba3382aa9b';
How can I product above query with sequelize to return distinct rows. I also tried distinct: true but it doesn't make any change. With this option query works and returns result but no distinct is there in the query generated.
The DISTINCT syntax in Postgres should look like this.
SELECT DISTINCT column AS alias FROM table;
DISTINCT is a clause and not function so you need to use literal.
Product.findAll({
attributes:[[sequelize.literal('DISTINCT "product"."id"'), 'product.id']],
...
})

Knex, Objection.js, How to sort by number of associations

I have an Express API using Postgres via Knex and Objection.
I want to set up a Model method or scope that returns an array of Parent model instances in order of number of associated Children.
I have looked through the Knex an Objection docs
I have seen the following SQL query that will fit, but trying to figure out how to do this in Knex:
SELECT SUM(O.TotalPrice), C.FirstName, C.LastName
FROM [Order] O JOIN Customer C
ON O.CustomerId = C.Id
GROUP BY C.FirstName, C.LastName
ORDER BY SUM(O.TotalPrice) DESC
This is how it should be done with knex (https://runkit.com/embed/rj4e0eo1d27f):
function sum(colName) {
return knex.raw('SUM(??)', [colName]);
}
knex('Order as O')
.select(sum('O.TotalPrice'), 'C.FirstName', 'C.LastName')
.join('Customer C', 'O.CustomerId', 'C.Id')
.groupBy('C.FirstName', 'C.LastName')
.orderBy(sum('O.TotalPrice'), 'desc')
// Outputs:
// select SUM("O"."TotalPrice"), "C"."FirstName", "C"."LastName"
// from "Order" as "O"
// inner join "Customer C" on "O"."CustomerId" = "C"."Id"
// group by "C"."FirstName", "C"."LastName"
// order by SUM("O"."TotalPrice") desc
But if you are really using objection.js then you should setup models for your Order and Customer tables and do something like this:
await Order.query()
.select(sum('TotalPrice'), 'c.FirstName', 'c.LastName')
.joinRelated('customer as c')
.groupBy('c.FirstName', 'c.LastName')
.orderBy(sum('TotalPrice'), 'desc')
In case anyone is interested, I just included the raw SQL query as follows:
router.get('/leaderboard', async (req, res) => {
let results = await knex.raw('SELECT users_id, username, COUNT(acts.id) FROM acts INNER JOIN users ON acts.users_id = users.id GROUP BY users_id, username ORDER BY COUNT(acts.id) DESC');
console.log(results);
res.json(results.rows);
});

How does nested SELECT and NOT IN work in knex

I'm trying to write this query in knex and am stuck.
I currently have 3 tables (group_tasks, completed_group_tasks and group_users)
I want to filter out the results when grouptask_id from completed_group_tasks is the same as the innerjoin.
SELECT * FROM group_tasks INNER JOIN group_users ON group_users.group_id = group_tasks.group_id WHERE user_id = 2 AND grouptask_id NOT IN (SELECT grouptask_id FROM completed_group_tasks WHERE user_id = 2)
I tried writing this:
db.from('group_users')
.select('groups.group_id', 'group_name')
.innerJoin('groups', 'group_users.group_id', 'groups.group_id')
.where({user_id: user_id})
.whereNotIn('grouptask_id', function() {
this.from('completed_group_tasks')
.select('grouptask_id')
.where({user_id: user_id})
})
This fails stating column "grouptask_id" does not exist
Subquery in Knex needs to be a separate Knex builder.
db.from('group_users')
.select('groups.group_id', 'group_name')
.innerJoin('groups', 'group_users.group_id', 'groups.group_id')
.where({ user_id: user_id })
.whereNotIn(
'grouptask_id',
db
.from('completed_group_tasks')
.select('grouptask_id')
.where({ user_id: user_id }),
);

I have a issue in Loopback

I have the following SQL:
SELECT *
FROM table1 INNER JOIN table2 ON table1.id = table2.id_table1
WHERE table2.column_name = 'value';
I have tried
{include:'table2',where:{'table2.column':'value'}}
but can't. What should I do?
this works for me
include: {
relation: 'table2',
scope: {
fields: ['fields', 'you', 'want'],
where: {
column: 'value'
}
}
}
in case it's not working, you need to make sure you have right relations in your table1.json and table2.json file
loopback does not support inner join it only support left join you can use raw query to achieve your requirement try something like this
yourmodalname.customremotemethod= function(ctx,options, cb) {
const ds = yourmodalname.dataSource
var query ="SELECT * FROM table1 INNER JOIN table2 ON table1.id =table2.id_table1 WHERE table2.column_name = 'value'";
ds.connector.query(query, function(err, res){
if(err){
cb(null,err)
}else{
cb(null,res)
}
});
};

node-postgres LEFT JOIN query

I am attempting to effect a join query in node-postgres (pg) with the following function but am getting a syntax error. The problem is the join query, everything else works fine. What is the correct way to format a join query in pg?
exports.bigBook = function(req, res) {
var bookNumber = req.params.id;
pool.connect(function(err, client, done) {
if (err) { return console.error('error fetching client from pool', err);}
client.query('SELECT * FROM book WHERE id = $1 LEFT JOIN author
ON (book.author = author.auth_id)'), [bookNumber], function (err, results) {
client.release();
res.send(results.rows);
};
})
}
The LEFT JOIN is part of the FROM clause, so you'll have to move the WHERE clause to the end of the query.