Skip to content

Commit

Permalink
strange
Browse files Browse the repository at this point in the history
  • Loading branch information
JPryce-Aklundh committed Jan 21, 2025
1 parent d6c403d commit 1582ead
Showing 1 changed file with 47 additions and 61 deletions.
108 changes: 47 additions & 61 deletions modules/ROOT/pages/subqueries/call-subquery.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,9 @@ CREATE (teamA:Team {name: 'Team A'}),
(playerF:Player {name: 'Player F', age: 35}),
(playerA)-[:PLAYS_FOR]->(teamA),
(playerB)-[:PLAYS_FOR]->(teamA),
(playerC)-[:PLAYS_FOR]->(teamA),
(playerD)-[:PLAYS_FOR]->(teamB),
(playerE)-[:PLAYS_FOR]->(teamC),
(playerF)-[:PLAYS_FOR]->(teamC),
(playerA)-[:FRIEND_OF]->(playerB),
(playerA)-[:FRIEND_OF]->(playerC),
(playerB)-[:FRIEND_OF]->(playerF),
(playerC)-[:FRIEND_OF]->(playerD),
(teamA)-[:OWES {dollars: 1500}]->(teamB),
(teamA)-[:OWES {dollars: 3000}]->(teamB),
(teamB)-[:OWES {dollars: 1700}]->(teamC),
Expand Down Expand Up @@ -93,7 +88,6 @@ CALL () {
SET p.age = p.age + 1
RETURN p.age AS newAge
}
WITH x, newAge
MATCH (p:Player {name: 'Player A'})
RETURN x AS iteration, newAge, p.age AS totalAge
----
Expand Down Expand Up @@ -140,7 +134,7 @@ RETURN t AS team, players
| players
| (:Team {name: "Team A"})
| [(:Player {name: "Player C", age: 19}), (:Player {name: "Player B", age: 23}), (:Player {name: "Player A", age: 24})]
| (:Player {name: "Player B", age: 23}), (:Player {name: "Player A", age: 24})]
| (:Team {name: "Team B"})
| [(:Player {name: "Player D", age: 30})]
Expand All @@ -161,7 +155,6 @@ Using a `CALL` subquery can therefore reduce the amount of heap memory required
Variables from the outer scope must be explicitly imported into the inner scope of the `CALL` subquery, either by using a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] or an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] (deprecated).
As the subquery is evaluated for each incoming input row, the imported variables are assigned the corresponding values from that row.


[[variable-scope-clause]]
=== The variable scope clause

Expand Down Expand Up @@ -279,7 +272,7 @@ RETURN count(t) AS totalTeams, totalPlayers

[NOTE]
=====
As of Neo4j 5.23, it is deprecated to use `CALL` subqueries without a variable scope clause.
`CALL` subqueries without a variable scope clause are deprecated.
.Deprecated
[source, cypher]
Expand Down Expand Up @@ -423,7 +416,6 @@ RETURN largeLists
====


[[optional-call]]
== Optional subquery calls

Expand All @@ -433,60 +425,60 @@ Similar to xref:clauses/optional-match.adoc[`OPTIONAL MATCH`] any empty rows pro
.Difference between using `CALL` and `OPTIONAL CALL`
====
This example, which finds the friends of each `Player` and xref:functions/aggregating.adoc#functions-count[counts] the number of friends per player, highlights the difference between using `CALL` and `OPTIONAL CALL`.
This example, which finds the team that each `Player` plays for, highlights the difference between using `CALL` and `OPTIONAL CALL`.
.Regular subquery `CALL`
[source, cypher]
----
MATCH (p:Player)
CALL (p) {
MATCH (p)-[:FRIEND_OF]->(friend:Player)
RETURN friend
MATCH (p)-[:PLAYS_FOR]->(team:Team)
RETURN team
}
RETURN p.name AS playerName, count(friend) AS numberOfFriends
ORDER BY numberOfFriends
RETURN p.name AS playerName, team.name AS team
----
.Optional subquery `CALL`
.Result
[role="queryresult",options="header,footer",cols="2*m"]
|===
| playerName | numberOfFriends
| playerName | team
| "Player B" | 1
| "Player C" | 1
| "Player A" | 2
| "Player A" | "Team A"
| "Player B" | "Team A"
| "Player D" | "Team B"
| "Player E" | "Team C"
| "Player F" | "Team C"
2+d|Rows: 3
2+d|Rows: 5
|===
Note that no results are returned for `Player D`, `Player E`, and `Player F`, since they have no outgoing `FRIEND_OF` relationships connected to them.
Note that no results are returned for `Player C`, since they are not connected to any `Team` with a `PLAYS_FOR` relationship.
.Query using regular `OPTIONAL CALL`
[source, cypher]
----
MATCH (p:Player)
OPTIONAL CALL (p) {
MATCH (p)-[:FRIEND_OF]->(friend:Player)
RETURN friend
MATCH (p)-[:PLAYS_FOR]->(team:Team)
RETURN team
}
RETURN p.name AS playerName, count(friend) AS numberOfFriends
ORDER BY numberOfFriends
RETURN p.name AS playerName, team.name AS team
----
Now, all `Player` nodes, regardless of whether they have any friends or not, are returned.
(Those without any outgoing `FRIEND_OF` relationships are returned with the result `0` because `count()` ignores `null` values.)
Now all `Player` nodes, regardless of whether they have any `PLAYS_FOR` relationships connected to a `Team`, are returned.
.Result
.Result
[role="queryresult",options="header,footer",cols="2*m"]
|===
| playerName | numberOfFriends
| playerName | team
| "Player D" | 0
| "Player E" | 0
| "Player F" | 0
| "Player B" | 1
| "Player C" | 1
| "Player A" | 2
| "Player A" | "Team A"
| "Player B" | "Team A"
| "Player C" | NULL
| "Player D" | "Team B"
| "Player E" | "Team C"
| "Player F" | "Team C"
2+d|Rows: 6
|===
Expand All @@ -496,8 +488,8 @@ Now, all `Player` nodes, regardless of whether they have any friends or not, are
[[call-execution-order]]
== Execution order of CALL subqueries

The order in which subqueries are executed is not defined.
If a query result depends on the order of execution of subqueries, an `ORDER BY` clause should precede the `CALL` clause.
The order in which rows from the outer scope are passed into subqueries is not defined.
If the results of the subquery depend on the order of these rows, use an `ORDER BY` clause before the `CALL` clause to guarantee a specific processing order for the rows.

.Ordering results before `CALL` subquery
====
Expand Down Expand Up @@ -591,13 +583,13 @@ UNION
ORDER BY p.age DESC
LIMIT 1
}
RETURN p.name AS name, p.age AS age
RETURN p.name AS playerName, p.age AS age
----
.Result
[role="queryresult",options="header,footer",cols="2*<m"]
|===
| name | age
| playerName | age
| "Player C" | 19
| "Player F" | 35
2+d|Rows: 2
Expand Down Expand Up @@ -642,39 +634,33 @@ The result of the `CALL` subquery is the combined result of evaluating the subqu

.`CALL` subquery changing returned rows of outer query
====
The following example finds the name of each `Player` and the names of their friends.
No rows are returned for the `Player` nodes without any `FRIEND_OF` relationships, the number of results of the subquery thus changed the number of results of the enclosing query.
The following example finds the name of each `Player` and the team they play for.
No rows are returned for `Player C`, since they are not connected to a `Team` with a `PLAYS_FOR` relationship.
The number of results of the subquery thus changed the number of results of the enclosing query.
.Find the friends of players
[source, cypher]
----
MATCH (p:Player)
CALL (p) {
MATCH (p)-[:FRIEND_OF]->(p2:Player)
RETURN p2.name AS friend
MATCH (p)-[:PLAYS_FOR]->(team:Team)
RETURN team.name AS team
}
RETURN p.name AS player, friend
RETURN p.name AS playerName, team
----
.Result
[role="queryresult",options="header,footer",cols="2*<m"]
[role="queryresult",options="header,footer",cols="2*m"]
|===
| player
| friend
| "Player A"
| "Player B"
| "Player A"
| "Player C"
| "Player B"
| "Player F"
| playerName | team
| "Player C"
| "Player D"
| "Player A" | "Team A"
| "Player B" | "Team A"
| "Player D" | "Team B"
| "Player E" | "Team C"
| "Player F" | "Team C"
2+d|Rows: 4
2+d|Rows: 5
|===
====
Expand Down Expand Up @@ -772,7 +758,7 @@ Labels added: 18

* `CALL` subqueries optimize data handling and query efficiency, and can perform changes to the database.

* `CALL` subqueries enable progressive data transformation and can accumulate results across multiple row executions.
* `CALL` subqueries allow for row-by-row data transformation and enable the accumulation of results across multiple rows, facilitating complex operations that depend on intermediate or aggregated data.

* `CALL` subqueries can only refer to variables from the enclosing query if they are explicitly imported by either a variable scope clause or an importing `WITH` clause (deprecated).

Expand All @@ -782,4 +768,4 @@ Labels added: 18

* An `ORDER BY` clause can be used before `CALL` subqueries to ensure a specific order.

* `CALL` subqueries can be used in combination with `UNION` to process and aggregate different parts of a query result.
* `CALL` subqueries can be used in combination with `UNION` to process and aggregate different parts of a query result.

0 comments on commit 1582ead

Please sign in to comment.