--- title: 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}`)