# NEXT
{bdg-primary-line}`GQL clause` {bdg-secondary-line}`Added in 2.18`
Chains two queries end to end: the rows the first query returns become the input
rows of the second.
## Synopsis
query NEXT query [ NEXT query ] ...
bold keywords · italic placeholders you supply · [ ] optional · ... repeatable. See Syntax conventions.
## Description
`NEXT` turns the result table of the query on its left into the driving table of
the query on its right. It is the composition operator `WITH` performs inside a
single query, promoted to a boundary between two whole queries.
- The query left of `NEXT` must end with `RETURN`.
- The boundary **resets scope**: only the columns that `RETURN` produced are
visible on the right. Every other variable is gone.
- Columns cross the boundary with their own types. A vertex is still a vertex, an
edge still an edge, a path still a path.
- `NEXT` is left-associative, so `A NEXT B NEXT C` composes as `(A NEXT B) NEXT C`.
- A [`UNION`](union.md), `INTERSECT` or `EXCEPT` composite may stand on either side.
- `NEXT` is accepted at the start of a statement and inside `EXPLAIN` and
`PREPARE`. It is not accepted inside a subquery, in either the `CALL { }` body
or a subquery value expression.
## Parameters
query
: A complete query. The one on the left of `NEXT` must end with `RETURN`, and every
column it returns must be named. An unaliased expression raises `expression in
WITH must be aliased (use AS)`. The query on the right is a fresh one. It begins
with a clause that can open a query (`MATCH`, `OPTIONAL MATCH`, `CREATE`,
`INSERT`, `MERGE`, `LOAD FROM`, `UNWIND`, `FOR`, `CALL`, `LET`, `RETURN` or
`FINISH`). It can also begin with a clause that operates on the carried table
(`WITH`, `FILTER`, `ORDER BY`, `SKIP`, `OFFSET` or `LIMIT`). It ends the way any
query ends: with `RETURN`, `FINISH` or a write clause.
## Examples
Every example runs against [the example dataset](../../get_started/example-dataset.md).
Carry the films one director made into a second query that finds their casts.
`NEXT` and an intermediate `WITH` compose the same two steps. Switch tabs to
compare:
::::{tab-set}
:::{tab-item} GQL — NEXT
```cypher
MATCH (p:person {name: 'Christopher Nolan'})-[:directed]->(m:movie)
RETURN m
NEXT
MATCH (a:person)-[:acted_in]->(m)
RETURN m.title AS film, a.name AS actor ORDER BY film;
```
:::
:::{tab-item} Cypher — WITH
```cypher
MATCH (p:person {name: 'Christopher Nolan'})-[:directed]->(m:movie)
WITH m
MATCH (a:person)-[:acted_in]->(m)
RETURN m.title AS film, a.name AS actor ORDER BY film;
```
:::
::::
```
film | actor
----------------+-----------------------
"Inception" | "Leonardo DiCaprio"
"Interstellar" | "Matthew McConaughey"
(2 rows)
```
`m` crosses the boundary as a vertex, so the second query re-traverses from it.
### Filter an aggregate computed by the first query
`FILTER` cannot open a standalone query, but it can open the query after `NEXT`.
That gives an aggregate a `HAVING`-style filter without an extra `WITH`:
```cypher
MATCH (p:person)-[:acted_in]->(m:movie)
RETURN p.name AS actor, count(m) AS films
NEXT
FILTER films > 2
RETURN actor, films ORDER BY actor;
```
```
actor | films
-------------------------+-------
"Arnold Schwarzenegger" | 3
"Keanu Reeves" | 4
(2 rows)
```
### Chain three queries
Each `NEXT` is another boundary, evaluated left to right:
```cypher
MATCH (m:movie) RETURN m.genre AS genre
NEXT
RETURN DISTINCT genre AS g
NEXT
RETURN count(g) AS genres;
```
```
genres
--------
3
(1 row)
```
### Reach a variable the first query did not return
Only returned columns survive the boundary, so a reference to anything else fails
at parse time:
```cypher
MATCH (p:person {name: 'Christopher Nolan'})-[:directed]->(m:movie)
RETURN m
NEXT
RETURN p.name;
```
```
ERROR: variable does not exist
LINE 4: RETURN p.name;
^
```
## Notes
`NEXT` costs nothing at run time. The boundary is built by rewriting the left
query's `RETURN` into the `WITH` the clause pipeline already places between clause
groups. The two tab-set queries above therefore plan identically.
Two guards report the misuse directly rather than as a syntax error. A left query
that does not end with `RETURN` raises `a query statement before NEXT must end
with RETURN`. A left query ending in `FINISH` raises
`FINISH cannot be followed by NEXT`.
The last query in a chain still has to end the statement properly. `ORDER BY`,
`SKIP`, `OFFSET` and `LIMIT` are clauses in their own right, but none of them can
terminate a query. A chain that stops on one raises `Cypher query must end with
RETURN, FINISH or update clause`. Follow it with `RETURN` or `FINISH`.
`next` is an unreserved keyword, so it remains usable as a variable, label or
property name.
## Compatibility
```{admonition} GQL conformance
:class: gql-conformance
Implements the GQL `` of the *procedure body* (ISO/IEC 39075:2024
§9.2), Feature GQ20, "Advanced linear composition with NEXT".
- **Supported** — chaining query statements, left-associative multi-chaining, the
scope reset at the boundary, and a set-operation composite on either side.
- **Not supported** — the optional `YIELD` clause the standard allows between
`NEXT` and the following statement (`NEXT YIELD a, b …`), which raises a syntax
error. Project and rename in the preceding `RETURN` instead.
Track status in the [GQL conformance matrix](../../appendix/gql-conformance.md).
```
### openCypher
openCypher has no `NEXT`. Composition there is always the `WITH` form shown in the
tab set above, which AgensGraph accepts unchanged.
## See also
- [`WITH`](with.md) — the Cypher analogue, inside one query
- [`LET`](let.md) {bdg-secondary-line}`GQL` — add columns without a boundary
- [`FILTER`](filter.md) {bdg-secondary-line}`GQL` — the clause `NEXT` makes available first
- [`FINISH`](finish.md) {bdg-secondary-line}`GQL`
- [`RETURN`](return.md) — what the left query has to end with
- [GQL conformance matrix](../../appendix/gql-conformance.md)