Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knex.js subqueries on MySQL left join

Tags:

mysql

knex.js

I'm kind of new with Knex.js query builder and I'm currently having trouble with one somehow simple MySQL select. Here it is :

SELECT orders.*, coalesce(x.unread, 0) AS unread_messages 
FROM orders
LEFT JOIN
    (SELECT id_order, COUNT(*) AS unread
     FROM chats
     WHERE read_by_user = 0
     GROUP BY id_order) AS x
ON x.id_order = orders.id_order
WHERE id_customer = 42
ORDER BY date_submitted;

I'm a bit lost reading Knex's doc, but should I use .joinRaw for the join and knex.raw for the coalesce command ?

like image 887
Jean-Philippe Bergeron Avatar asked Jan 04 '18 15:01

Jean-Philippe Bergeron


People also ask

How do I use a KNEX query for subselects?

Though it isn't directly possible to use a knex query for subselects, you can get around that issue by passing in a stringified var q = knex(knex.raw('subselectTable AS t2')) .select( ...) .where( ...); return knex(knex.raw('yourTable AS t1')) .select( ...) .join( // This is the important part.

Is there a way to do sub-queries for joins?

Currently there isn't support for doing sub-queries for joins, and the Knex.Raw would be the best way to go about it - though there's no reason that couldn't be allowed - I'll look into adding a way to do it using an independent query: Would this be what you're looking for? Hi @tgriesser thank you !!

What is KNEX JS?

This Knex.js Tutorial will be beginner friendly with code examples so all users can benefit most from it. Knex.js is a very popular Node.js SQL query builder with supports both callback and promise based coding styles, transaction with save points support for all major SQL databases with common api interface for all queries.

How do I pull data from two tables in KNEX?

To achieve this outcome, we need to join two tables ( users, and posts) and create a query in Knex that pulls data from both tables. This code creates a route that retrieves the posts with a specific user id. If we want to grab data from the users table, though, we need a join statement in our query.


2 Answers

https://runkit.com/embed/1olni3l68kn4

knex('orders')
  .select(
    'orders.*', 
    knex.raw('coalesce(??, 0) as ??', ['x.unread', 'unread_messages'])
  )
  .leftJoin(
    knex('charts')
      .select('id_order', knex.raw('count(*) as ??', ['unread']))
      .where('read_by_use', 0).groupBy('id_order').as('x'), 
    'x.id_order', 
    'orders.id_order'
  )
  .where('id_customer', 42)
  .orderBy('date_submitted')

produces

select 
  `orders`.*, coalesce(`x`.`unread`, 0) as `unread_messages` 
from `orders` 
left join (
  select `id_order`, count(*) as `unread` 
  from `charts` 
  where `read_by_use` = ? 
  group by `id_order`
) as `x` 
on `x`.`id_order` = `orders`.`id_order` 
where `id_customer` = ? 
order by `date_submitted` asc
like image 188
Mikael Lepistö Avatar answered Sep 20 '22 15:09

Mikael Lepistö


For those who land here: that's my working solution with the great help of @Mikael.

selectFromWhere = db('orders')
  .select('orders.*', db.raw('IFNULL(??, 0) as ??', ['x.unread', 'unread_messages']))
  .leftJoin(
    db('chats')
      .select('id_order', db.raw('count(*) as ??', ['unread']))
      .where('read_by_user', 0)
      .groupBy('id_order')
      .as('x'),
    'x.id_order',
    'orders.id_order'
  )
  .where('id_customer', req.user.id_customer);
like image 31
Jean-Philippe Bergeron Avatar answered Sep 19 '22 15:09

Jean-Philippe Bergeron