CALL {} (subquery)
Introduction
CALL allows to execute subqueries, i.e. queries inside of other queries.
Subqueries allow you to compose queries, which is especially useful when working with UNION
or aggregations.
The |
A subquery is evaluated for each incoming input row and may produce an arbitrary number of output rows. Every output row is then combined with the input row to build the result of the subquery. That means that a subquery will influence the number of rows. If the subquery does not return any rows, there will be no rows available after the subquery.
There are restrictions on what queries are allowed as subqueries and how they interact with the enclosing query:
-
A subquery must end with a
RETURN
clause. -
A subquery cannot refer to variables from the enclosing query.
-
A subquery cannot return variables with the same names as variables in the enclosing query.
-
All variables that are returned from a subquery are afterwards available in the enclosing query.
The following graph is used for the examples below:
N0 [ label = "{Person, Child|name = \'Alice\'\lage = 20\l}" ] N0 -> N2 [ color = "#2e3436" fontcolor = "#2e3436" label = "CHILD_OF\n" ] N0 -> N1 [ color = "#4e9a06" fontcolor = "#4e9a06" label = "FRIEND_OF\n" ] N1 [ label = "{Person|name = \'Bob\'\lage = 27\l}" ] N2 [ label = "{Person, Parent|name = \'Charlie\'\lage = 65\l}" ] N3 [ label = "{Person|name = \'Dora\'\lage = 30\l}" ]
Post-union processing
Subqueries can be used to process the results of a UNION
query further.
This example query finds the youngest and the oldest person in the database and orders them by name.
CALL {
MATCH (p:Person)
RETURN p
ORDER BY p.age ASC
LIMIT 1
UNION
MATCH (p:Person)
RETURN p
ORDER BY p.age DESC
LIMIT 1
}
RETURN p.name, p.age
ORDER BY p.name
p.name | p.age |
---|---|
|
|
|
|
Rows: 2 |
If different parts of a result should be matched differently, with some aggregation over the whole results, subqueries need to be used. This example query finds all persons with friends in one part of the union and all children with parents in the other part. Subsequently the number of friends and parents is counted together.
CALL {
MATCH (p:Person)-[:FRIEND_OF]->(other:Person)
RETURN p, other
UNION
MATCH (p:Child)-[:CHILD_OF]->(other:Parent)
RETURN p, other
}
RETURN DISTINCT p.name, count(other)
p.name | count(other) |
---|---|
|
|
Rows: 1 |
Aggregation and side-effects
Subqueries can be useful to do aggregations for each row and to isolate side-effects.
This example query creates five Clone
nodes for each existing person.
The aggregation ensures that cardinality is not changed by the subquery.
Without this, the result would be five times as many rows.
MATCH (p:Person)
CALL {
UNWIND range(1, 5) AS i
CREATE (c:Clone)
RETURN count(c) AS numberOfClones
}
RETURN p.name, numberOfClones
p.name | numberOfClones |
---|---|
|
|
|
|
|
|
|
|
Rows: 4 |
Correlated subqueries
This functionality is currently only available in Neo4j Fabric, see Operations Manual → Fabric. |
A correlated subquery is a subquery that uses variables defined outside of the CALL
clause.
To be able to use a variable in this way, the variable must be explicitly imported into the subquery.
Importing variables into subqueries
Variables are imported into a subquery using an importing WITH
clause.
As the subquery is evaluated for each incoming input row, the imported variables get bound to the corresponding values from the input row in each evaluation.
UNWIND [0, 1, 2] AS x
CALL {
WITH x
RETURN x * 10 AS y
}
RETURN x, y
x | y |
---|---|
|
|
|
|
|
|
Rows: 3 |
An importing WITH
clause must:
-
Consist only of simple references to outside variables - e.g.
WITH x, y, z
. Aliasing or expressions are not supported in importingWITH
clauses - e.g.WITH a AS b
orWITH a + 1 AS b
. -
Be the first clause of a subquery (or the second clause, if directly following a
USE
clause).
Aggregation on imported variables
Aggregations in subqueries are scoped to the subquery evaluation, also for imported variables, as shown in the following example:
UNWIND [0, 1, 2] AS x
CALL {
WITH x
RETURN max(x) AS xMax
}
RETURN x, xMax
x | xMax |
---|---|
|
|
|
|
|
|
Rows: 3 |
The aggregation max(x)
observes only a single value of x
in each evaluation of the subquery, and thus simply evaluates to that same value.