diff --git a/modules/ROOT/images/graph_order_by_clause.svg b/modules/ROOT/images/graph_order_by_clause.svg
index a42046fcc..a571834d7 100644
--- a/modules/ROOT/images/graph_order_by_clause.svg
+++ b/modules/ROOT/images/graph_order_by_clause.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/modules/ROOT/pages/clauses/order-by.adoc b/modules/ROOT/pages/clauses/order-by.adoc
index a5e4a78a4..f18ad4db2 100644
--- a/modules/ROOT/pages/clauses/order-by.adoc
+++ b/modules/ROOT/pages/clauses/order-by.adoc
@@ -1,118 +1,154 @@
-:description: `ORDER BY` is a sub-clause following `RETURN` or `WITH`, and it specifies that the output should be sorted and how.
-
-[[query-order]]
= ORDER BY
+:description: Information about Cypher's `ORDER BY` subclause.
+:table-caption!:
-`ORDER BY` specifies how the output of a clause should be sorted.
-It be used as a sub-clause following `RETURN` or `WITH`.
+`ORDER BY` is a subclause that determines how the results of a xref:clauses/return.adoc[`RETURN`] or xref:clauses/with.adoc[`WITH`] clause are ordered.
+It can also be used as a standalone clause, either on its own or in combination with `SKIP`/`OFFSET` or `LIMIT`.
-`ORDER BY` relies on comparisons to sort the output, see xref:values-and-types/ordering-equality-comparison.adoc[Ordering and comparison of values].
-You can sort on many different values, e.g. node/relationship properties, the node/relationship ids, or on most expressions.
+`ORDER BY` defaults to sorting results in an ascending order, though it can be modified to sort results in a xref:clauses/order-by.adoc#ascending-descending-order[descending order].
-[NOTE]
-====
+`ORDER BY` relies on comparisons to sort the output (see xref:values-and-types/ordering-equality-comparison.adoc[] for more details).
+You can sort on different values, such as node or relationship properties, IDs, or the result of expressions.
+
+[IMPORTANT]
Unless `ORDER BY` is used, Neo4j does not guarantee the row order of a query result.
-====
+
[[example-graph]]
== Example graph
-The following graph is used for the examples below:
+A graph with the following schema is used for the examples below:
-image::graph_order_by_clause.svg[width="600", role="middle"]
+image::graph_order_by_clause.svg[width="400", role="middle"]
To recreate it, run the following query against an empty Neo4j database:
[source, cypher, role=test-setup]
----
-CREATE
- (andy: Person {name: 'Andy', age: 34, length: 170}),
- (bernard: Person {name: 'Bernard', age: 36}),
- (charlotte: Person {name: 'Charlotte', age: 32, length: 185}),
- (andy)-[:KNOWS]->(bernard),
- (bernard)-[:KNOWS]->(charlotte)
+CREATE (o1:Order {id: 'ORD-001', orderDate: datetime('2024-05-01T10:00:00'), total: 550, status: 'shipped'}),
+ (o2:Order {id: 'ORD-002', orderDate: datetime('2024-05-02T14:30:00'), total: 1000, status: 'pending'}),
+ (o3:Order {id: 'ORD-003', orderDate: datetime('2024-05-03T09:15:00'), total: 550, status: 'pending'}),
+ (o4:Order {id: 'ORD-004', orderDate: datetime('2024-05-04T12:45:00'), total: 200}),
+ (o5:Order {id: 'ORD-005', orderDate: datetime('2024-05-05T15:00:00'), total: 800, status: 'shipped'}),
+
+ (i1:Item {name: 'Phone', price: 500}),
+ (i2:Item {name: 'Laptop', price: 1000}),
+ (i3:Item {name: 'Headphones', price: 250}),
+ (i4:Item {name: 'Charger', price: 50}),
+ (i5:Item {name: 'Keyboard', price: 200}),
+
+ (o1)-[:CONTAINS]->(i1),
+ (o1)-[:CONTAINS]->(i4),
+ (o2)-[:CONTAINS]->(i2),
+ (o3)-[:CONTAINS]->(i1),
+ (o3)-[:CONTAINS]->(i4),
+ (o4)-[:CONTAINS]->(i5),
+ (o5)-[:CONTAINS]->(i1),
+ (o5)-[:CONTAINS]->(i3),
+ (o5)-[:CONTAINS]->(i4)
----
-[[order-nodes-by-property]]
-== Order nodes by property
-`ORDER BY` is used to sort the output.
+[[basic-examples]]
+== Basic examples
-.Query
+.Order by property values
+=====
+
+`ORDER BY` can be used to sort the result by property values.
+
+.Order by node property
// tag::clauses_order_by[]
[source, cypher]
----
-MATCH (n)
-RETURN n.name, n.age
-ORDER BY n.name
+MATCH (o:Order)
+RETURN o.id AS order,
+ o.total AS total
+ ORDER BY total
----
// end::clauses_order_by[]
-The nodes are returned, sorted by their name.
+The nodes are returned, sorted by the value of the `total` properties in an ascending order.
.Result
[role="queryresult",options="header,footer",cols="2*(:Item) } AS itemCount
+ ORDER BY itemCount
+----
.Result
-[role="queryresult",options="header,footer",cols="3*
-| "Andy" | 34 | 170
-| "Charlotte" | 32 | 185
-3+d|Rows: 3
+| order | itemCount
+
+| "ORD-002" | 1
+| "ORD-004" | 1
+| "ORD-001" | 2
+| "ORD-003" | 2
+| "ORD-005" | 3
+
+2+d|Rows: 5
|===
+=====
-[[order-nodes-in-descending-order]]
-== Order nodes in descending order
+[[order-by-values-not-in-result]]
+== Order by values not in the result
-By adding `DESC[ENDING]` after the variable to sort on, the sort will be done in reverse order.
+`ORDER BY` can sort by values that are not included in the result set.
+That is, the sort key does not need to be part of the preceding `RETURN` or `WITH` clause.
+For example, the query below sorts orders based on how many items they contain, even though that count is not returned.
-.Query
+.Order by values not in the returned results
[source, cypher]
----
-MATCH (n)
-RETURN n.name, n.age
-ORDER BY n.name DESC
+MATCH (o:Order)
+RETURN o.id AS order
+ ORDER BY COUNT { (o)-[:CONTAINS]->(:Item) }
----
-The example returns the nodes, sorted by their name in reverse order.
+.Result
+[role="queryresult",options="header,footer",cols="1*(i:Item)
+RETURN o.id AS order,
+ o.total,
+ collect(i.name) AS items
+----
.Result
[role="queryresult",options="header,footer",cols="3* | "Bernard" | 36
-3+d|Rows: 3
+| order | total | items
+
+| "ORD-005" | 800 | ["Phone", "Headphones", "Charger"]
+
+3+d|Rows: 1
+|===
+
+[[null]]
+== Null values
+
+When sorting, `null` values appear last in ascending order and first in descending order.
+
+.Sort on null property
+[source, cypher]
+----
+MATCH (o:Order)
+RETURN o.id AS order,
+ o.status AS status
+ ORDER BY status DESC
+----
+
+.Result
+[role="queryresult",options="header,footer",cols="2*(i:Item)
+WITH o, i
+ ORDER BY i.price DESC
+RETURN o.id AS order,
+ collect(i.name || " ($" || toString(i.price) || ")") AS orderedListOfItems
----
-The list of names built from the `collect` aggregating function contains the names in order of the `age` property.
-
.Result
-[role="queryresult",options="header,footer",cols="1*(i:Item)
+WITH o.id AS order,
+ i.name AS item
+ ORDER BY o.orderDate
+RETURN order, item
+----
+
+* If the `RETURN` or `WITH` performs an aggregation or uses `DISTINCT` only the projected variables from either operation are available to `ORDER BY`.
+This is because these operations alter the number of rows produced by the clause and any variables not explicitly projected are discarded.
-It is also not allowed to use aggregating expressions in the `ORDER BY` sub-clause if they are not also listed in the projecting clause.
-This rule is to make sure that `ORDER BY` does not change the results, only the order of them.
+.`ORDER BY` following a `WITH` clause projecting an aggregated value
+[source, cypher, role=test-fail]
+----
+MATCH (o:Order)-[:CONTAINS]->(i:Item)
+WITH collect(o.id) AS orders,
+ i.name AS items
+ ORDER BY o.orderDate
+RETURN orders, items
+----
+.Error message
+[source, error]
+----
+In a WITH/RETURN with DISTINCT or an aggregation, it is not possible to access variables declared before the WITH/RETURN: o
+----
+
+[[indexes]]
== ORDER BY and indexes
The performance of Cypher queries using `ORDER BY` on node properties can be influenced by the existence and use of an index for finding the nodes.
@@ -247,43 +467,45 @@ Read more about this capability in xref::indexes/search-performance-indexes/usin
`ORDER BY` can be used as a standalone clause, or in conjunction with `SKIP`/`OFFSET` or `LIMIT`.
-
.Standalone use of `ORDER BY`
// tag::clauses_order_by_standalone[]
[source, cypher]
----
-MATCH (n)
-ORDER BY n.name
-RETURN collect(n.name) AS names
+MATCH (i:Item)
+ORDER BY i.price
+RETURN collect(i.name || " ($" || toString(i.price) || ")") AS orderedPriceList
----
// end::clauses_order_by_standalone[]
.Result
[role="queryresult",options="header,footer",cols="1*