JOIN Examples

Simple Join

Use join to create a new query builder with an additional table join. The on option is used to specify the join condition.

$.from(Contact).join(Order, { on:(c,o) => $`${c.id} = ${o.contactId}` }).select('*')

Custom Join Types

Use leftJoin, rightJoin, fullJoin, crossJoin to create a new query builder with a specific join type.

db.all($.from(Contact).leftJoin(Order, { on:(c,o) => $`${c.id} = ${o.contactId}` }).select('*')) db.all($.from(Contact).rightJoin(Order, { on:(c,o) => $`${c.id} = ${o.contactId}` }).select('*')) db.all($.from(Contact).fullJoin(Order, { on:(c,o) => $`${c.id} = ${o.contactId}` }).select('*')) db.all($.from(Contact).crossJoin(Order, { on:(c,o) => $`${c.id} = ${o.contactId}` }).select('*'))

Multiple Joins

Multiple joins can be chained together to create complex queries. A new query builder is created for each join that's added containing references for all tables in the query in the order they were added.

These references can be used in where, select, groupBy, orderBy methods to reference columns from each table.

The *join APIs are instead passed a reference to the previous joined table and the current table, they also include a reference to the primary table as the last reference (e.g. OrderItem on:(_,i,o)).

$.from(Order) .leftJoin(Contact, { on:(o,c) => $`${o.contactId} = ${c.id}` }) .join(OrderItem, { on:(_,i,o) => $`${i.orderId} = ${o.id}` }) .leftJoin(Product, { on:(i,p) => $`${i.sku} = ${p.sku}` }) .where((o,c,i,p) => $`${c.id} = ${1} AND ${p.cost} > ${100}`) .select((o,c,i,p) => $`${o.id}, ${c.name}, ${i.qty}, ${p.name}`)

Aliases

Each joined table can be assigned an alias using the as option. This alias is then used to reference the table in the query.

$.from(Order,'o') .leftJoin(Contact, { as:'c', on:(o,c) => $`${o.contactId} = ${c.id}` }) .join(OrderItem, { as:'i', on:(_,i,o) => $`${i.orderId} = ${o.id}` }) .leftJoin(Product, { as:'p', on:(i,p) => $`${i.sku} = ${p.sku}` }) .where((o,c,i,p) => $`${c.id} = ${1} AND ${p.cost} > ${100}`) .select((o,c,i,p) => $`${o.id}, ${c.name}, ${i.qty}, ${p.name}`)

External References

Queries can be joined on external references which can be used across multiple query builders that can be composed together to create complex queries that reference other queries.

const [ o, c, i, p ] = [ $.ref(Order,'o'), $.ref(Contact,'c'), $.ref(OrderItem,'i'), $.ref(Product,'p') ] const recentOrder = $.from(Order,'o2') .where(o2 => $`${o2.contactId} = ${c.id}`) .select(o2 => $`MAX(${o2.createdAt})`) db.all($.from(o) .leftJoin(c, $`${o.contactId} = ${c.id}`) .join(i, $`${i.orderId} = ${o.id}`) .leftJoin(p, $`${i.sku} = ${p.sku}`) .where`${o.createdAt} = (${recentOrder})` .select`${o.id}, ${c.name}, ${i.qty}, ${p.name}`)

JOIN query builder

When more flexibility is needed you can create a JOIN query builder with $.join() that can be added to other SELECT query builders to create complex queries.

$.from(Contact,'c') .join(Order, { on:(c,o) => $`${c.id} = ${o.contactId}` }) .join( $.join(OrderItem,Order,Product).as('i').leftJoin((i, o, p) => $`${o.id} = ${i.orderId} LEFT JOIN ${p} ON ${i.sku} = ${p.sku}`) ) .select('*')

Cache complex JOIN queries

For improved performance and to simplify complex queries, complex joins can be reused and memoized by returning isolated cloned query builders with clone().

const contactOrderItems = (() => { const q = $.from(Contact,'c') .join(Order, { as:'o', on:(c,o) => $`${c.id} = ${o.contactId}` }) .join(OrderItem, { as:'i', on:(o,i) => $`${o.id} = ${i.orderId}` }) return () => q.clone() })() const [q1, q2, q3] = [...Array(3)].map(contactOrderItems) const [ c, o, i ] = q1.refs db.all(q1.where`${c.id} = ${10}`) db.all(q2.where`${o.contactId} = ${20}`) db.all(q3.where`${i.orderId} = ${100}`)