# LET {bdg-primary-line}`GQL clause` {bdg-secondary-line}`Added in 2.18` Adds computed values to the working record without dropping columns already in scope. It is the GQL-standard counterpart to Cypher's `WITH *, expr AS v`. ## Synopsis
LET variable = expression [, variable = expression ] ...

bold keywords · italic placeholders you supply · [ ] optional · ... repeatable. See Syntax conventions.

## Description `LET` introduces one or more new variables into the current row, computed from expressions over variables already in scope. Unlike `WITH`, it is **additive**: every binding in scope is carried forward automatically, so `LET` can never accidentally drop a variable from the pipeline. - Each variable is **introduce-only**. A name already in scope cannot be rebound, inside the body of a subquery expression or of an importing `CALL { }` as much as at the top level. - Expressions are evaluated **row-by-row**; aggregates are not allowed. - `LET` may **lead** a query or sit in the middle, but cannot terminate one. It is the clause to open a statement with, because [`WITH`](with.md) in that position is SQL's common table expression. ## Parameters variable : Name of the new binding. Must not already be in scope. Visible to every clause that follows. expression : Any row-wise value expression: property access, arithmetic, function calls, `CASE`, list/map constructors. Evaluated once per input row. ## Examples These examples run against [the example dataset](../../get_started/example-dataset.md). ### Add a derived value and keep everything in scope The GQL and Cypher forms are equivalent. Switch tabs to compare: ::::{tab-set} :::{tab-item} GQL — LET ```cypher MATCH (p:person) LET age_in_2026 = 2026 - p.born RETURN p.name AS name, age_in_2026 ORDER BY age_in_2026 LIMIT 3; ``` ::: :::{tab-item} Cypher — WITH ```cypher MATCH (p:person) WITH *, 2026 - p.born AS age_in_2026 RETURN p.name AS name, age_in_2026 ORDER BY age_in_2026 LIMIT 3; ``` ::: :::: ``` name | age_in_2026 -------------------+------------- "Ryan Gosling" | 46 "Neill Blomkamp" | 47 "Sam Worthington" | 50 (3 rows) ``` The difference is what happens to `p`. `LET` carries it forward automatically. The `WITH` form has to ask for it with `*`, and a `WITH` that forgets the `*` drops `p`, so the `RETURN` then fails. ### Lead a query with computed values Because `LET` is additive it can open a statement, seeding values with nothing yet in scope: ```cypher LET radius = 7, area = 3.14159 * 7 * 7 RETURN radius, area; ``` ``` radius | area --------+----------- 7 | 153.93791 (1 row) ``` ### Introduce-only A name already in scope cannot be rebound: ```cypher MATCH (p:person) LET p = 1 RETURN p; ``` ``` ERROR: variable "p" already exists HINT: LET cannot redefine an existing variable; use a different name. ``` ```{admonition} GQL conformance :class: gql-conformance Implements the GQL *LET statement* (ISO/IEC 39075:2024 §14.7). - **Supported** — variable definition, multiple bindings, leading position, and row-wise expressions. - **Not supported** — `LET` over aggregate expressions. Track status in the [conformance matrix](../../appendix/gql-conformance.md). ``` ```{note} `LET` became a **reserved keyword** in 2.18. If you used `let` as a label or variable name in an earlier version, quote it (`"let"` — double quotes, not backticks) or rename it. Property keys and `RETURN` aliases are unaffected. ``` ## See also - [`WITH`](with.md) — the Cypher analogue - [`NEXT`](next.md) {bdg-secondary-line}`GQL` - [`RETURN`](return.md) - [GQL conformance matrix](../../appendix/gql-conformance.md)