From 02d3035752882a57e87600b96fcf89ac23e3a4e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?=
<112686610+JPryce-Aklundh@users.noreply.github.com>
Date: Thu, 6 Mar 2025 11:17:45 +0100
Subject: [PATCH 1/7] initial
---
modules/ROOT/content-nav.adoc | 1 +
modules/ROOT/images/let_clause.svg | 1 +
.../gql-conformance/supported-optional.adoc | 5 +
modules/ROOT/pages/clauses/index.adoc | 21 +-
modules/ROOT/pages/clauses/let.adoc | 408 ++++++++++++++++++
modules/ROOT/pages/syntax/keywords.adoc | 1 +
6 files changed, 429 insertions(+), 8 deletions(-)
create mode 100644 modules/ROOT/images/let_clause.svg
create mode 100644 modules/ROOT/pages/clauses/let.adoc
diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc
index 1a27ec07d..1a09a10a2 100644
--- a/modules/ROOT/content-nav.adoc
+++ b/modules/ROOT/content-nav.adoc
@@ -18,6 +18,7 @@
** xref:clauses/filter.adoc[]
** xref:clauses/finish.adoc[]
** xref:clauses/foreach.adoc[]
+** xref:clauses/let.adoc[]
** xref:clauses/limit.adoc[]
** xref:clauses/load-csv.adoc[]
** xref:clauses/match.adoc[]
diff --git a/modules/ROOT/images/let_clause.svg b/modules/ROOT/images/let_clause.svg
new file mode 100644
index 000000000..60701e662
--- /dev/null
+++ b/modules/ROOT/images/let_clause.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc
index 164229a74..0f930c4ab 100644
--- a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc
+++ b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc
@@ -178,6 +178,11 @@ For example, GQL’s graph reference values `CURRENT_GRAPH` and `CURRENT_PROPERT
| xref:clauses/filter.adoc[`FILTER`]
|
+| GQ09
+| `LET` statement
+| xref:clauses/let.adoc[`LET`]
+|
+
| GQ13
| `ORDER BY` and page statement: `LIMIT`
| xref:clauses/limit.adoc[`LIMIT`], xref:clauses/order-by.adoc[`ORDER BY`]
diff --git a/modules/ROOT/pages/clauses/index.adoc b/modules/ROOT/pages/clauses/index.adoc
index 07192fe4f..a7eb885e4 100644
--- a/modules/ROOT/pages/clauses/index.adoc
+++ b/modules/ROOT/pages/clauses/index.adoc
@@ -35,21 +35,26 @@ The returned expressions may all be aliased using `AS`.
|===
| Clause | Description
-m| xref::clauses/return.adoc[RETURN ... [AS]]
-| Defines what to include in the query result set.
-
-m| xref::clauses/with.adoc[WITH ... [AS]]
-| Allows query parts to be chained together, piping the results from one to be used as starting points or criteria in the next.
-
-m| xref::clauses/unwind.adoc[UNWIND ... [AS]]
-| Expands a list into a sequence of rows.
+m| xref::clauses/let.adoc[LET]
+| Adds filters to queries.
+label:new[Introduced in Neo4j 2025.03]
m| xref::clauses/filter.adoc[FILTER]
| Adds filters to queries.
+label:new[Introduced in Neo4j 2025.03]
m| xref::clauses/finish.adoc[FINISH]
| Defines a query to have no result.
+m| xref::clauses/return.adoc[RETURN ... [AS]]
+| Defines what to include in the query result set.
+
+m| xref::clauses/unwind.adoc[UNWIND ... [AS]]
+| Expands a list into a sequence of rows.
+
+m| xref::clauses/with.adoc[WITH ... [AS]]
+| Allows query parts to be chained together, piping the results from one to be used as starting points or criteria in the next.
+
|===
[[reading-sub-clauses]]
diff --git a/modules/ROOT/pages/clauses/let.adoc b/modules/ROOT/pages/clauses/let.adoc
new file mode 100644
index 000000000..13af9bc97
--- /dev/null
+++ b/modules/ROOT/pages/clauses/let.adoc
@@ -0,0 +1,408 @@
+= LET
+:description: Information about Cypher's `LET` clause.
+:table-caption!:
+:page-role: new-2025.03
+
+`LET` binds expressions to variables.
+For queries involving several chained expressions, it can be a more succinct and readable alternative to xref:clauses/with.adoc[`WITH`].
+Unlike `WITH`, `LET` cannot limit the scope of variables available to subsequent clauses.
+Nor can it be used for aggregations or in combination with `DISTINCT`; it can only be used to bind new variables.
+
+[[example-graph]]
+== Example graph
+
+A graph with the following schema is used for the examples below:
+
+image::let_clause.svg[width="600",role="middle"]
+
+To recreate the graph, run the following query against an empty Neo4j database.
+
+[source, cypher, role=test-setup]
+----
+CREATE (techCorp:Supplier {name: 'TechCorp', email: 'contact@techcorp.com'}),
+ (foodies:Supplier {name: 'Foodies Inc.', email: 'info@foodies.com'}),
+
+ (laptop:Product {name: 'Laptop', price: 1000}),
+ (phone:Product {name: 'Phone', price: 500}),
+ (headphones:Product {name: 'Headphones', price: 250}),
+ (chocolate:Product {name: 'Chocolate', price: 5}),
+ (coffee:Product {name: 'Coffee', price: 10}),
+
+ (amir:Customer {firstName: 'Amir', lastName: 'Rahman', email: 'amir.rahman@example.com', discount: 0.1}),
+ (keisha:Customer {firstName: 'Keisha', lastName: 'Nguyen', email: 'keisha.nguyen@example.com', discount: 0.2}),
+ (mateo:Customer {firstName: 'Mateo', lastName: 'Ortega', email: 'mateo.ortega@example.com', discount: 0.05}),
+ (hannah:Customer {firstName: 'Hannah', lastName: 'Connor', email: 'hannah.connor@example.com', discount: 0.15}),
+ (leila:Customer {firstName: 'Leila', lastName: 'Haddad', email: 'leila.haddad@example.com', discount: 0.1}),
+ (niko:Customer {firstName: 'Niko', lastName: 'Petrov', email: 'niko.petrov@example.com', discount: 0.25}),
+ (yusuf:Customer {firstName: 'Yusuf', lastName: 'Abdi', email: 'yusuf.abdi@example.com', discount: 0.1}),
+
+ (amir)-[:BUYS {date: date('2024-10-09')}]->(laptop),
+ (amir)-[:BUYS {date: date('2025-01-10')}]->(chocolate),
+ (keisha)-[:BUYS {date: date('2023-07-09')}]->(headphones),
+ (mateo)-[:BUYS {date: date('2025-03-05')}]->(chocolate),
+ (mateo)-[:BUYS {date: date('2025-03-05')}]->(coffee),
+ (mateo)-[:BUYS {date: date('2024-04-11')}]->(laptop),
+ (hannah)-[:BUYS {date: date('2023-12-11')}]->(coffee),
+ (hannah)-[:BUYS {date: date('2024-06-02')}]->(headphones),
+ (leila)-[:BUYS {date: date('2023-05-17')}]->(laptop),
+ (niko)-[:BUYS {date: date('2025-02-27')}]->(phone),
+ (niko)-[:BUYS {date: date('2024-08-23')}]->(headphones),
+ (niko)-[:BUYS {date: date('2024-12-24')}]->(coffee),
+ (yusuf)-[:BUYS {date: date('2024-12-24')}]->(chocolate),
+ (yusuf)-[:BUYS {date: date('2025-01-02')}]->(laptop),
+
+ (techCorp)-[:SUPPLIES]->(laptop),
+ (techCorp)-[:SUPPLIES]->(phone),
+ (techCorp)-[:SUPPLIES]->(headphones),
+ (foodies)-[:SUPPLIES]->(chocolate),
+ (foodies)-[:SUPPLIES]->(coffee)
+----
+
+[[assigning-expressions-to-variables]]
+== Assigning expressions to a variable
+
+Both `Let` and `WITH` can be used to assign variables to an expression:
+
+* `LET` syntax: `LET = , = `
+* `WITH` syntax: `WITH AS , AS `
+
+[.tabbed-example]
+=====
+[.include-with-LET]
+======
+.LET
+[source, cypher]
+----
+MATCH (c:Customer)
+LET fullName = c.firstName + ' ' + c.lastName
+RETURN fullName
+----
+======
+[.include-with-WITH]
+======
+.WITH
+[source, cypher]
+----
+MATCH (c:Customer)
+WITH c.firstName + ' ' + c.lastName AS fullName
+RETURN fullName
+----
+======
+=====
+
+.Result
+[role="queryresult",options="header,footer", cols="1*(p:Product)
+LET supplier = s.name, product = p.name
+RETURN supplier, product
+----
+
+.Result
+[role="queryresult",options="header,footer", cols="2* = ` is a substitute for `WITH *, AS `, not `WITH AS ` (which would drop any variables present in the preceding clause not referenced in ``).
+
+.Variables in scope: comparing `LET` and `WITH`
+=====
+
+Any variable not explicitly referenced by `WITH` (or carried over by `WITH *`) is dropped from the scope of subsequent clauses.
+
+.Not allowed -- Referencing a variable dropped by `WITH`
+[source, cypher, role=test-fail]
+----
+MATCH (s:Supplier)-[:SUPPLIES]->(p:Product)
+WITH s.name AS supplier
+RETURN supplier, p.name AS product
+----
+
+.Error message
+[source, error]
+----
+Variable `p` not defined
+----
+
+`LET`, however, cannot regulate which variables are in scope.
+Replacing `WITH` with `LET` in the above query would, therefore, return results.
+
+.`LET` does not drop variables
+[source, cypher]
+----
+MATCH (s:Supplier)-[:SUPPLIES]->(p:Product)
+LET supplier = s.name
+RETURN supplier, p.name AS product
+----
+
+.Result
+[role="queryresult",options="header,footer", cols="2*= 500
+LET isAffordable = NOT isExpensive
+LET discountCategory = CASE
+ WHEN isExpensive THEN 'High-end'
+ ELSE 'Budget'
+END
+RETURN p.name AS product, p.price AS price, isAffordable, discountCategory
+ORDER BY price
+----
+
+.Result
+[role="queryresult",options="header,footer", cols="4*= 500 AS isExpensive
+WITH p, isExpensive, NOT isExpensive AS isAffordable
+WITH p, isExpensive, isAffordable,
+ CASE
+ WHEN isExpensive THEN 'High-end'
+ ELSE 'Budget'
+ END AS discountCategory
+RETURN p.name AS product, p.price AS price, isAffordable, discountCategory
+ORDER BY price
+----
+
+=====
+
+[[aggregations-distinct]]
+=== Aggregations and `DISTINCT`
+
+Unlike `WITH`, `LET` cannot perform aggregations or be combined with `DISTINCT`.
+For example, in the following query, `WITH` could not be replaced by `LET`:
+
+.Combining `WITH DISTINCT` and aggregations on expressions
+[source, source]
+----
+MATCH (c:Customer)-[:BUYS]->(p:Product)
+WITH DISTINCT c, sum(p.price) AS totalSpent
+RETURN c.firstName AS customer, totalSpent
+----
+
+.Result
+[role="queryresult",options="header,footer", cols="2*(p:Product)
+WITH DISTINCT c, sum(p.price) AS totalSpent
+LET fullName = c.firstName + ' ' + c.lastName,
+RETURN fullName, totalSpent
+----
+
+.Result
+[role="queryresult",options="header,footer", cols="2*(p:Product)<--(s:Supplier)
+LET fullname = c.firstName + ' ' + c.lastName,
+ effectivePrice = p.price * (1 - c.discount)
+LET message = fullname + " bought " + p.name + " for $" + effectivePrice + " after a " + (c.discount * 100) + "% discount"
+RETURN b.date AS date, message, s.email AS toSupplier
+ORDER BY date
+----
+
+.Result
+[role="queryresult",options="header,footer", cols="1m, 2m, 1m"]
+|===
+| date | message | toSupplier
+
+| 2023-05-17 | "Leila Haddad bought Laptop for $900.0 after a 10.0% discount" | "contact@techcorp.com"
+| 2023-07-09 | "Keisha Nguyen bought Headphones for $200.0 after a 20.0% discount" | "contact@techcorp.com"
+| 2023-12-11 | "Hannah Connor bought Coffee for $8.5 after a 15.0% discount" | "info@foodies.com"
+| 2024-04-11 | "Mateo Ortega bought Laptop for $950.0 after a 5.0% discount" | "contact@techcorp.com"
+| 2024-06-02 | "Hannah Connor bought Headphones for $212.5 after a 15.0% discount" | "contact@techcorp.com"
+| 2024-08-23 | "Niko Petrov bought Headphones for $187.5 after a 25.0% discount" | "contact@techcorp.com"
+| 2024-10-09 | "Amir Rahman bought Laptop for $900.0 after a 10.0% discount" | "contact@techcorp.com"
+| 2024-12-24 | "Yusuf Abdi bought Chocolate for $4.5 after a 10.0% discount" | "info@foodies.com"
+| 2024-12-24 | "Niko Petrov bought Coffee for $7.5 after a 25.0% discount" | "info@foodies.com"
+| 2025-01-02 | "Yusuf Abdi bought Laptop for $900.0 after a 10.0% discount" | "contact@techcorp.com"
+| 2025-01-10 | "Amir Rahman bought Chocolate for $4.5 after a 10.0% discount" | "info@foodies.com"
+| 2025-02-27 | "Niko Petrov bought Phone for $375.0 after a 25.0% discount" | "contact@techcorp.com"
+| 2025-03-05 | "Mateo Ortega bought Chocolate for $4.75 after a 5.0% discount" | "info@foodies.com"
+| 2025-03-05 | "Mateo Ortega bought Coffee for $9.5 after a 5.0% discount" | "info@foodies.com"
+
+3+d| Rows: 14
+|===
+
+=====
+
+.Scenario 2: Supplier gift card distribution based on customer spending
+=====
+
+The example calculates the `customerRevenue` for each `Customer` after applying their `discount` on each `Product` they bought. Customers are then categorized into three groups based on their total spending: Category `A` for those who spent more than `850`, Category `B` for those who spent more than `350` but less than or equal to `850`, and Category `C` for those who spent `350` or less.
+Category `C` customers are excluded from the results using the xref:clauses/filter.adoc[`FILTER`] clause, leaving only Category `A` and `B` customers eligible for a gift card.
+The `amount` in the gift card is assigned based on the category, with with Category `A` receiving `20` and Category `B` receiving `10`.
+The details of the gift card are then sent to the `email` of the relevant customers.
+
+This example highlights how `LET` can be used to succinctly chain expressions, and also that it cannot be used to perform aggregations.
+
+.Calculate customer gift card distribution based on spending
+[source, cypher]
+----
+MATCH (customer:Customer)-[bought:BUYS]->(product:Product)
+LET effectivePrice = product.price * (1 - customer.discount)
+WITH customer, bought, sum(effectivePrice) AS customerRevenue
+LET category = CASE
+ WHEN customerRevenue > 850 THEN 'A'
+ WHEN customerRevenue > 350 THEN 'B'
+ ELSE 'C'
+ END
+FILTER category <> 'C'
+LET amount = CASE
+ WHEN category = 'A' THEN 20
+ WHEN category = 'B' THEN 10
+END
+LET message = {
+ type: 'giftcard',
+ addressee: customer.firstName + ' ' + customer.lastName,
+ amount: amount,
+ year: bought.date.year
+}
+RETURN message, customer.email AS toCustomer, customerRevenue
+ORDER BY amount
+----
+
+.Result
+[role="queryresult",options="header,footer", cols="3m, 2m, 1m"]
+|===
+| message | toCustomer | customerRevenue
+
+| {amount: 10, addressee: "Niko Petrov", type: "giftcard", year: 2025} | "niko.petrov@example.com" | 375.0
+| {amount: 20, addressee: "Amir Rahman", type: "giftcard", year: 2024} | "amir.rahman@example.com" | 900.0
+| {amount: 20, addressee: "Mateo Ortega", type: "giftcard", year: 2024} | "mateo.ortega@example.com" | 950.0
+| {amount: 20, addressee: "Leila Haddad", type: "giftcard", year: 2023} | "leila.haddad@example.com" | 900.0
+| {amount: 20, addressee: "Yusuf Abdi", type: "giftcard", year: 2025} | "yusuf.abdi@example.com" | 900.0
+
+3+d|Rows: 5
+|===
+=====
\ No newline at end of file
diff --git a/modules/ROOT/pages/syntax/keywords.adoc b/modules/ROOT/pages/syntax/keywords.adoc
index dc71b20a2..792c0160a 100644
--- a/modules/ROOT/pages/syntax/keywords.adoc
+++ b/modules/ROOT/pages/syntax/keywords.adoc
@@ -215,6 +215,7 @@ Note that with future functionality, Cypher may be extended with additional keyw
* `LABEL`
* `LABELS`
* `LEADING`
+* `LET`
* `LIMITROWS`
* `LIST`
* `LOAD`
From 8b2dd89bfe399647392d08742b7d131332665ca5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?=
<112686610+JPryce-Aklundh@users.noreply.github.com>
Date: Thu, 6 Mar 2025 11:19:51 +0100
Subject: [PATCH 2/7] correction
---
modules/ROOT/pages/clauses/index.adoc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ROOT/pages/clauses/index.adoc b/modules/ROOT/pages/clauses/index.adoc
index a7eb885e4..79a1f61db 100644
--- a/modules/ROOT/pages/clauses/index.adoc
+++ b/modules/ROOT/pages/clauses/index.adoc
@@ -36,7 +36,7 @@ The returned expressions may all be aliased using `AS`.
| Clause | Description
m| xref::clauses/let.adoc[LET]
-| Adds filters to queries.
+| Assigns expressions to variables.
label:new[Introduced in Neo4j 2025.03]
m| xref::clauses/filter.adoc[FILTER]
From 5d6c2dd84a109bf72cba132568e48e99b309c2f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?=
<112686610+JPryce-Aklundh@users.noreply.github.com>
Date: Thu, 6 Mar 2025 11:28:16 +0100
Subject: [PATCH 3/7] cleanup
---
modules/ROOT/pages/clauses/let.adoc | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/modules/ROOT/pages/clauses/let.adoc b/modules/ROOT/pages/clauses/let.adoc
index 13af9bc97..d2c75cd9a 100644
--- a/modules/ROOT/pages/clauses/let.adoc
+++ b/modules/ROOT/pages/clauses/let.adoc
@@ -122,11 +122,11 @@ RETURN supplier, product
| "TechCorp" | "Laptop"
| "TechCorp" | "Phone"
+| "TechCorp" | "Headphones"
| "Foodies Inc." | "Chocolate"
| "Foodies Inc." | "Coffee"
2+d|Rows: 4
-
|===
[[let-and-with-differences]]
@@ -200,7 +200,7 @@ The fact that `LET` does not drop variables means that it can be used to chain e
.Chaining expressions: comparing `LET` and `WITH`
=====
-The below query shows that variables bound by a `LET` clause be referenced in subsequent `LET` clauses without being explicitly carried over.
+The below query shows that variables bound by a `LET` clause be referenced by subsequent clauses without being explicitly carried over.
Specifically, the variable `isExpensive` is created in the first `LET` clause and referenced again in the subsequent clauses.
Note also that the variable `p`, bound in the `MATCH` clause, is available in the final `RETURN` clause despite not being referenced in any of `LET` clauses.
@@ -309,7 +309,7 @@ RETURN fullName, totalSpent
[[advanced-examples]]
== Advanced examples
-The following scenarios demonstrates how `LET`, and its ability to chain expressions, can be used in more advanced queries:
+The following examples demonstrates how `LET`, and its ability to chain expressions, can be used in more advanced queries:
.Scenario 1: Supplier notification on customer purchases and discounts
=====
From 6751c9560cd65a83021e6d0f96c3d9fbbf67f259 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?=
<112686610+JPryce-Aklundh@users.noreply.github.com>
Date: Thu, 6 Mar 2025 13:23:21 +0100
Subject: [PATCH 4/7] update to 2025.04
---
modules/ROOT/pages/clauses/let.adoc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ROOT/pages/clauses/let.adoc b/modules/ROOT/pages/clauses/let.adoc
index d2c75cd9a..5ee8053cd 100644
--- a/modules/ROOT/pages/clauses/let.adoc
+++ b/modules/ROOT/pages/clauses/let.adoc
@@ -1,7 +1,7 @@
= LET
:description: Information about Cypher's `LET` clause.
:table-caption!:
-:page-role: new-2025.03
+:page-role: new-2025.04
`LET` binds expressions to variables.
For queries involving several chained expressions, it can be a more succinct and readable alternative to xref:clauses/with.adoc[`WITH`].
From 58a42a4089703c73a09892a13c829313e00ba2d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?=
<112686610+JPryce-Aklundh@users.noreply.github.com>
Date: Thu, 6 Mar 2025 15:37:15 +0100
Subject: [PATCH 5/7] update image to include discount prop
---
modules/ROOT/images/let_clause.svg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ROOT/images/let_clause.svg b/modules/ROOT/images/let_clause.svg
index 60701e662..f77938445 100644
--- a/modules/ROOT/images/let_clause.svg
+++ b/modules/ROOT/images/let_clause.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
From 16ab50c7f12094058084b029eb839d2554cbf8ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?=
<112686610+JPryce-Aklundh@users.noreply.github.com>
Date: Mon, 10 Mar 2025 09:21:57 +0100
Subject: [PATCH 6/7] post-review corrections
---
modules/ROOT/pages/clauses/index.adoc | 17 +++++++------
modules/ROOT/pages/clauses/let.adoc | 36 ++++++++-------------------
2 files changed, 20 insertions(+), 33 deletions(-)
diff --git a/modules/ROOT/pages/clauses/index.adoc b/modules/ROOT/pages/clauses/index.adoc
index 79a1f61db..fce6b31ee 100644
--- a/modules/ROOT/pages/clauses/index.adoc
+++ b/modules/ROOT/pages/clauses/index.adoc
@@ -17,6 +17,11 @@ This set is refined and augmented by subsequent parts of the query.
|===
| Clause | Description
+
+m| xref::clauses/filter.adoc[FILTER]
+| Adds filters to queries.
+label:new[Introduced in Neo4j 2025.04]
+
m| xref::clauses/match.adoc[MATCH]
| Specify the patterns to search for in the database.
@@ -35,17 +40,13 @@ The returned expressions may all be aliased using `AS`.
|===
| Clause | Description
-m| xref::clauses/let.adoc[LET]
-| Assigns expressions to variables.
-label:new[Introduced in Neo4j 2025.03]
-
-m| xref::clauses/filter.adoc[FILTER]
-| Adds filters to queries.
-label:new[Introduced in Neo4j 2025.03]
-
m| xref::clauses/finish.adoc[FINISH]
| Defines a query to have no result.
+m| xref::clauses/let.adoc[LET]
+| Binds values to variables.
+label:new[Introduced in Neo4j 2025.04]
+
m| xref::clauses/return.adoc[RETURN ... [AS]]
| Defines what to include in the query result set.
diff --git a/modules/ROOT/pages/clauses/let.adoc b/modules/ROOT/pages/clauses/let.adoc
index 5ee8053cd..01a6ad455 100644
--- a/modules/ROOT/pages/clauses/let.adoc
+++ b/modules/ROOT/pages/clauses/let.adoc
@@ -5,7 +5,7 @@
`LET` binds expressions to variables.
For queries involving several chained expressions, it can be a more succinct and readable alternative to xref:clauses/with.adoc[`WITH`].
-Unlike `WITH`, `LET` cannot limit the scope of variables available to subsequent clauses.
+Unlike `WITH`, `LET` does not drop variables from the scope of subsequent clauses.
Nor can it be used for aggregations or in combination with `DISTINCT`; it can only be used to bind new variables.
[[example-graph]]
@@ -59,36 +59,23 @@ CREATE (techCorp:Supplier {name: 'TechCorp', email: 'contact@techcorp.com'}),
----
[[assigning-expressions-to-variables]]
-== Assigning expressions to a variable
+== Bind values to variables
-Both `Let` and `WITH` can be used to assign variables to an expression:
+`LET` is used to bind variables to the results of expressions.
-* `LET` syntax: `LET = , = `
-* `WITH` syntax: `WITH AS , AS `
-
-[.tabbed-example]
-=====
-[.include-with-LET]
-======
-.LET
-[source, cypher]
+.Syntax
+[source, syntax]
----
-MATCH (c:Customer)
-LET fullName = c.firstName + ' ' + c.lastName
-RETURN fullName
+LET variable = expression, variable = expression
----
-======
-[.include-with-WITH]
-======
-.WITH
+
+.Using `LET` to bind a variable
[source, cypher]
----
MATCH (c:Customer)
-WITH c.firstName + ' ' + c.lastName AS fullName
+LET fullName = c.firstName + ' ' + c.lastName
RETURN fullName
----
-======
-=====
.Result
[role="queryresult",options="header,footer", cols="1* = ` is a substitute for `WITH *, AS `, not `WITH AS ` (which would drop any variables present in the preceding clause not referenced in ``).
.Variables in scope: comparing `LET` and `WITH`
@@ -286,7 +272,7 @@ RETURN c.firstName AS customer, totalSpent
----
MATCH (c:Customer)-[:BUYS]->(p:Product)
WITH DISTINCT c, sum(p.price) AS totalSpent
-LET fullName = c.firstName + ' ' + c.lastName,
+LET fullName = c.firstName + ' ' + c.lastName
RETURN fullName, totalSpent
----
From 05eff7cce8286a8feacd1f84c12309583fd4be9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?=
<112686610+JPryce-Aklundh@users.noreply.github.com>
Date: Mon, 10 Mar 2025 09:30:21 +0100
Subject: [PATCH 7/7] let to additions page
---
...precations-additions-removals-compatibility.adoc | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc
index 9d2a4e1af..63b2f457e 100644
--- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc
+++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc
@@ -209,6 +209,19 @@ a|
label:functionality[]
label:new[]
+[source, cypher, role="noheader"]
+----
+MATCH (s:Supplier)-[:SUPPLIES]->(p:Product)
+LET supplier = s.name
+RETURN supplier, p.name AS product
+----
+
+| New xref:clauses/let.adoc[`LET`] clause used to bind values to variables.
+
+a|
+label:functionality[]
+label:new[]
+
[source, cypher, role="noheader"]
----
UNWIND [1, 2, 3, 4, 5, 6] AS x