Skip to main content

Select Statement

Select() builds a SELECT query as a plain JS object graph and serializes it to dialect-correct SQL text on demand. It has no knowledge of any driver or connection — it only builds and renders SQL.

import { Select, Eq } from '@sqb/builder';

const query = Select('id', 'given_name', 'family_name')
.from('customers')
.where(Eq('active', true))
.orderBy('id')
.limit(10);

const { sql, params } = query.generate({ dialect: 'postgres' });

Select is dual-callable — call it as a plain function or with new, both return the same kind of instance:

const a = Select('id', 'name');
const b = new Select('id', 'name');

Full API reference: Select class.

Adding columns

Pass columns to the Select(...) constructor, or add them afterwards with .addColumn(). Both accept strings, arrays of strings (flattened automatically), or SQL element instances such as Field, Raw, or a sub-Select.

Select('id', 'given_name family_name'); // "field alias" shorthand
Select(['id', 'given_name'], 'family_name'); // arrays are flattened
Select().addColumn('id', 'given_name');
Select('id, given_name family_name, gender'); // one string, comma-split into 3 columns

A column string may include a table/schema prefix and an optional alias: 'schema1.table1.field1 f1'. If no columns are given at all (or addColumn() is never called), the query serializes to select *.

Select().from('customers').generate().sql;
// 'select * from customers'

To select a sub-query as a column, give it an alias with .as() — an alias is required for any sub-Select used as a column or table:

const sub = Select('id').from('orders').as('order_id');
Select(sub).from('customers');
// select (select id from orders) order_id from customers

from()

.from(...) accepts one or more table names (strings), TableName instances, Raw fragments, or sub-Select/Union queries (the latter two require .as()). Calling .from() again replaces the previous table list rather than appending to it.

Select().from('customers');
Select().from('schema1.customers c');
Select().from('customers', Raw('LATERAL func()'));

join()

See Joins for the full walkthrough of .join(), the JoinType enum, and the join element classes (InnerJoin, LeftJoin, ...).

where()

.where(...) accumulates conditions into an implicit top-level And. Calling .where() more than once keeps adding to the same And rather than replacing it.

Select().from('customers').where(Eq('active', true)).where(Eq('country', 'US'));
// where active = true and country = 'US'

See Operators and Conditions for the full list of condition operators and the object-literal shorthand.

groupBy() and orderBy()

Both accept column name strings or SQL element instances (GroupColumn / OrderColumn are constructed for you from strings). Order columns support a leading +/- or a trailing asc/desc/ascending/descending word:

Select().from('customers').groupBy('country').orderBy('-created_at', 'name asc');
// group by country order by created_at desc, name

as(), distinct(), limit(), offset()

Select('id').from('orders').as('o'); // alias, for use as a sub-select
Select('id', 'name').distinct().from('customers'); // select distinct id, name ...
Select().from('customers').limit(10).offset(20);

.limit() and .offset() coerce their argument to an integer. What SQL each produces depends on the target dialect — see Generating SQL per dialect.

comment()

Attaches an SQL comment block to the generated output, optionally restricted to specific dialects:

Select().from('customers').comment('Only fetch active rows');
// /*Only fetch active rows*/
// select * from customers

Select().from('customers').comment('Postgres only', ['postgres']);

Fetch events

Select (like every query type) is an EventEmitter. @sqb/connect uses the 'fetch' event to notify listeners as rows stream in; @sqb/builder itself only exposes the registration methods:

Select()
.from('customers')
.onFetch(row => console.log(row))
.onceFetch(row => console.log('first row', row));

generate()

.generate(options?) renders the query to SQL text. See Generating SQL per dialect for the full option set (dialect, prettyPrint, params, dialectVersion, strictParams) and the returned { sql, params, paramOptions, returningFields } shape, and The Dialect Plugin System for how pagination, identifier quoting, bind-parameter style, and other dialect-specific behavior are decided by whichever plugin package you've imported.