You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: modules/ROOT/pages/clauses/order-by.adoc
+58-54Lines changed: 58 additions & 54 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,31 +6,30 @@
6
6
`ORDER BY` is a subclause which specifies the order in which the output of a xref:clauses/return.adoc[`RETURN`] or xref:clauses/with.adoc[`WITH`] clause.
7
7
As of Neo4j 5.24, it can also be used as a standalone clause, either on its own or in combination with `SKIP`/`OFFSET` or `LIMIT`.
8
8
9
-
`ORDER BY` by default sorts results in an ascending order, though it can be modified to return results in a xref:clauses/order-by.adoc#ascending-descending-order[descending order].
9
+
`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].
10
10
11
11
`ORDER BY` relies on comparisons to sort the output (see xref:values-and-types/ordering-equality-comparison.adoc[] for more details).
12
12
You can sort on different values, such as node or relationship properties, IDs, or the result of expressions.
13
13
14
14
[IMPORTANT]
15
-
====
16
15
Unless `ORDER BY` is used, Neo4j does not guarantee the row order of a query result.
17
-
====
16
+
18
17
19
18
[[example-graph]]
20
19
== Example graph
21
20
22
-
The following graph is used for the examples below:
21
+
A graph with the following schema is used for the examples below:
@@ -154,7 +151,7 @@ Applications relying on internal Neo4j IDs are, as a result, brittle and can be
154
151
It is recommended to use application-generated IDs instead.
155
152
156
153
[[order-by-expression]]
157
-
== Order by expressions results
154
+
== Order by expressions
158
155
159
156
`ORDER BY` can be used to sort according to the results of an xref:expressions/index.adoc[expression].
160
157
The below query calculates a 10% discount on each order's `total` property value, and then orders the results by the discounted total.
@@ -173,9 +170,9 @@ RETURN o.id AS order,
173
170
|===
174
171
| order | discountedTotal
175
172
176
-
| "ORD-004" | 450.0
177
-
| "ORD-001" | 675.0
178
-
| "ORD-003" | 675.0
173
+
| "ORD-004" | 180.0
174
+
| "ORD-001" | 495.0
175
+
| "ORD-003" | 495.0
179
176
| "ORD-005" | 720.0
180
177
| "ORD-002" | 900.0
181
178
@@ -228,9 +225,9 @@ RETURN o.id AS order,
228
225
|===
229
226
| order | total
230
227
231
-
| "ORD-004" | 500
232
-
| "ORD-001" | 750
233
-
| "ORD-003" | 750
228
+
| "ORD-004" | 200
229
+
| "ORD-001" | 550
230
+
| "ORD-003" | 550
234
231
| "ORD-005" | 800
235
232
| "ORD-002" | 1000
236
233
@@ -255,9 +252,9 @@ RETURN o.id AS order,
255
252
256
253
| "ORD-002" | 1000
257
254
| "ORD-005" | 800
258
-
| "ORD-001" | 750
259
-
| "ORD-003" | 750
260
-
| "ORD-004" | 500
255
+
| "ORD-001" | 550
256
+
| "ORD-003" | 550
257
+
| "ORD-004" | 200
261
258
262
259
2+d|Rows: 5
263
260
|===
@@ -292,7 +289,7 @@ RETURN o.id AS order,
292
289
|===
293
290
294
291
[[null]]
295
-
== Ordering `null`
292
+
== Null values
296
293
297
294
When sorting, `null` values appear last in ascending order and first in descending order.
298
295
@@ -321,13 +318,12 @@ RETURN o.id AS order,
321
318
322
319
323
320
[[order-with]]
324
-
== Ordering in a `WITH` clause
321
+
== ORDER BY and the WITH clause
325
322
326
-
When `ORDER BY` is present on a `WITH` clause, the immediately following clause will receive records in the specified order.
323
+
When `ORDER BY` is present on a `WITH` clause, the immediately following clause will receive records in the specified order.
327
324
The ordering guarantee can be useful to exploit by operations which depend on the order in which they consume values.
328
-
For example, this can be used to control the order of items in the list produced by the xref:functions/aggregating.adoc#functions-collect[`collect()`] aggregating function.
325
+
For example, appending `ORDER BY` to a `WITH` clause can be used to control the order of items in the list produced by the xref:functions/aggregating.adoc#functions-collect[`collect()`] aggregating function.
329
326
The xref:clauses/merge.adoc[`MERGE`] and xref:clauses/set.adoc[`SET`] clauses also have ordering dependencies which can be controlled this way.
330
-
The order is not guaranteed to be retained after the following clause, unless that also has an `ORDER BY` subclause.
331
327
332
328
The below example uses `WITH` and `ORDER BY` to sort `Item` nodes by their `price` property, then the `collect()` in the subsequent `RETURN` clause builds an ordered list per order based on that sort.
The next query uses `ORDER BY` to sort `Item` nodes by order count, then creates a `discount` property with `SET` based on the order count:
355
+
[[aggregation-distinct]]
356
+
== Ordering aggregated or DISTINCT results
360
357
361
-
.`WITH`, `ORDER BY`, and `SET`
358
+
The variables available to `ORDER BY` depends on whether or not the preceding `RETURN` or `WITH` clause performs an aggregation to combine results or uses `DISTINCT` to remove duplicates.
359
+
360
+
* If the `RETURN` or `WITH` is not aggregating values or using `DISTINCT`, then `ORDER BY` can reference any variables referenced in the preceding `RETURN` or `WITH` clause.
361
+
362
+
.`ORDER BY` following a `WITH` clause excluding aggregation or `DISTINCT`
362
363
[source, cypher]
363
364
----
364
-
MATCH (i:Item)<-[:CONTAINS]-(o:Order)
365
-
WITH i,
366
-
count(o) AS orderCount
367
-
ORDER BY orderCount DESC
368
-
SET i.discount = CASE
369
-
WHEN orderCount < 2 THEN 0.10
370
-
ELSE 0.05
371
-
END
372
-
RETURN i.name AS item,
373
-
orderCount,
374
-
i.price AS originalPrice,
375
-
(i.price * (1 - i.discount)) AS discountedPrice
365
+
MATCH (o:Order)-[:CONTAINS]->(i:Item)
366
+
WITH o.id AS order,
367
+
i.name AS item
368
+
ORDER BY o.orderDate
369
+
RETURN order, item
376
370
----
377
371
378
-
== Ordering aggregated or DISTINCT results
372
+
* If the `RETURN` or `WITH` performs an aggregation or uses `DISTINCT` only the projected variables from either operation are available to `ORDER BY`.
373
+
This is because these operations alter the number of rows produced by the clause and any variables not explicitly projected are discarded.
379
374
380
-
In terms of scope of variables, `ORDER BY` follows special rules, depending on if the projecting `RETURN` or `WITH` clause is either aggregating or `DISTINCT`.
381
-
If it is an aggregating or `DISTINCT` projection, only the variables available in the projection are available.
382
-
If the projection does not alter the output cardinality (which aggregation and `DISTINCT` do), variables available from before the projecting clause are also available.
383
-
When the projection clause shadows already existing variables, only the new variables are available.
375
+
.`ORDER BY` following a `WITH` clause projecting an aggregated value
376
+
[source, cypher, role=test-fail]
377
+
----
378
+
MATCH (o:Order)-[:CONTAINS]->(i:Item)
379
+
WITH collect(o.id) AS orders,
380
+
i.name AS items
381
+
ORDER BY o.orderDate
382
+
RETURN orders, items
383
+
----
384
384
385
-
It is also not allowed to use aggregating expressions in the `ORDER BY` subclause if they are not also listed in the projecting clause.
386
-
This rule is to make sure that `ORDER BY` does not change the results, only the order of them.
385
+
.Error message
386
+
[source, error]
387
+
----
388
+
In a WITH/RETURN with DISTINCT or an aggregation, it is not possible to access variables declared before the WITH/RETURN: o
389
+
----
387
390
391
+
[[indexes]]
388
392
== ORDER BY and indexes
389
393
390
394
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.
0 commit comments