7.9.12. SQL-12 — distinct

distinct() flips a single bool flag on the analyzer’s SqlQuery and emits SELECT DISTINCT instead of plain SELECT. The rest of the chain (column list, WHERE, ORDER BY, LIMIT) composes normally.

7.9.12.1. Full-row DISTINCT

Without a _select, every column is in the row — DISTINCT deduplicates whole rows:

let all_rows <- _sql(db |> select_from(type<Car>) |> distinct())
// SELECT DISTINCT "Id", "Name", "Price" FROM "Cars"

7.9.12.2. Single-column DISTINCT

Project one column with _select(_.Field) and dedupe it:

let names <- _sql(db |> select_from(type<Car>)
                    |> _select(_.Name)
                    |> distinct())
// SELECT DISTINCT "Name" FROM "Cars"

7.9.12.3. Composes with _where

let names_over_100 <- _sql(db |> select_from(type<Car>)
                             |> _where(_.Price > 100)
                             |> _select(_.Name)
                             |> distinct())
// SELECT DISTINCT "Name" FROM "Cars" WHERE "Price" > ?

7.9.12.4. Set operations — deferred

UNION / INTERSECT / EXCEPT are out of chunk-4 scope. The chain analyzer is single-source today: every SELECT comes from one select_from(type<T>). Set operations bring in a second SqlQuery and need a multi-stage emitter — the same engine work joins and subqueries need.

Until that lands, work around set ops via the raw-SQL escape hatch (db |> exec(...) for DDL plus CREATE TEMP VIEW, then select_from the view; or drive the SQLite C API directly for multi-row reads of arbitrary SQL).

See also

Full source: tutorials/sql/12-distinct.das

Previous tutorial: SQL-11 — take and skip: Paging

Next tutorial: SQL-12b — Set operations