diff --git a/jOOQ-website/src/main/resources/manual-2.5.xml b/jOOQ-website/src/main/resources/manual-2.5.xml
index 3222efd7d2..19af5750dd 100644
--- a/jOOQ-website/src/main/resources/manual-2.5.xml
+++ b/jOOQ-website/src/main/resources/manual-2.5.xml
@@ -2107,6 +2107,18 @@ GROUP BY AUTHOR_ID
| O Alquimista, Brida |
+---------------------+
+
FIRST and LAST: Oracle's "ranked" aggregate functions
+
+ Oracle allows for restricting aggregate functions using the KEEP() clause, which is supported by jOOQ. In Oracle, some aggregate functions (MIN, MAX, SUM, AVG, COUNT, VARIANCE, or STDDEV) can be restricted by this clause, hence also allows for specifying it. Here are a couple of examples using this clause:
+
+
+
+SUM(BOOK.AMOUNT_SOLD)
+ KEEP(DENSE_RANK FIRST ORDER BY BOOK.AUTHOR_ID)
+sum(BOOK.AMOUNT_SOLD)
+ .keepDenseRankFirstOrderBy(BOOK.AUTHOR_ID)
+
+
User-defined aggregate functions
jOOQ also supports using your own user-defined aggregate functions. See the manual's section about for more details.
@@ -2121,7 +2133,134 @@ GROUP BY AUTHOR_ID
Window functions
-
+
+ Window functions
+
+ Most major RDBMS support the concept of window functions. jOOQ knows of implementations in DB2, Oracle, Postgres, SQL Server, and Sybase SQL Anywhere, and supports most of their specific syntaxes. Note, that H2 and HSQLDB have implemented ROW_NUMBER() functions, without true windowing support.
+
+
+ As previously discussed, any can be transformed into a window function using the over() method. See the chapter about for details. In addition to those, there are also some more window functions supported by jOOQ, as declared in the :
+
+
+ rowNumber();
+ WindowOverStep rank();
+ WindowOverStep denseRank();
+ WindowOverStep percentRank();
+
+// Windowing functions
+ WindowIgnoreNullsStep firstValue(Field field);
+ WindowIgnoreNullsStep lastValue(Field field)
+ WindowIgnoreNullsStep lead(Field field);
+ WindowIgnoreNullsStep lead(Field field, int offset);
+ WindowIgnoreNullsStep lead(Field field, int offset, T defaultValue);
+ WindowIgnoreNullsStep lead(Field field, int offset, Field defaultValue);
+ WindowIgnoreNullsStep lag(Field field);
+ WindowIgnoreNullsStep lag(Field field, int offset);
+ WindowIgnoreNullsStep lag(Field field, int offset, T defaultValue);
+ WindowIgnoreNullsStep lag(Field field, int offset, Field defaultValue);
+
+// Statistical functions
+ WindowOverStep cumeDist();
+ WindowOverStep ntile(int number);]]>
+
+
+ SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:
+
+
+ - Your JDBC driver or database already checks SQL syntax semantics
+ - Not all databases behave correctly according to the SQL standard
+
+
+ If possible, however, jOOQ tries to render missing clauses for you, if a given is more restrictive.
+
+ Some examples
+
+ Here are some simple examples of window functions with jOOQ:
+
+
+
+-- Sample uses of ROW_NUMBER()
+ROW_NUMBER() OVER()
+ROW_NUMBER() OVER(PARTITION BY 1)
+ROW_NUMBER() OVER(ORDER BY BOOK.ID)
+ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID)
+
+-- Sample uses of FIRST_VALUE
+FIRST_VALUE(BOOK.ID) OVER()
+FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER()
+FIRST_VALUE(BOOK.ID RESPECT NULLS) OVER()
+
+// Sample uses of rowNumber()
+rowNumber().over()
+rowNumber().over().partitionByOne()
+rowNumber().over().partitionBy(BOOK.AUTHOR_ID)
+rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID)
+
+// Sample uses of firstValue()
+firstValue(BOOK.ID).over()
+firstValue(BOOK.ID).ignoreNulls().over()
+firstValue(BOOK.ID).respectNulls().over()
+
+
+
+ An advanced window function example
+
+ Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method:
+
+
+
+SELECT booked_at, amount,
+ SUM(amount) OVER (PARTITION BY 1
+ ORDER BY booked_at
+ ROWS BETWEEN UNBOUNDED PRECEDING
+ AND CURRENT ROW) AS total
+ FROM transactions
+create.select(t.BOOKED_AT, t.AMOUNT,
+ sum(t.AMOUNT).over().partitionByOne()
+ .orderBy(t.BOOKED_AT)
+ .rowsBetweenUnboundedPreceding()
+ .andCurrentRow().as("total")
+ .from(TRANSACTIONS.as("t"));
+
+
+
+ Window functions created from ordered aggregate functions
+
+ In the previous chapter about , we have seen the concept of "ordered aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:
+
+
+
+SELECT LISTAGG(TITLE, ', ')
+ WITHIN GROUP (ORDER BY TITLE)
+ OVER (PARTITION BY BOOK.AUTHOR_ID)
+FROM BOOK
+create.select(listAgg(BOOK.TITLE, ", ")
+ .withinGroupOrderBy(BOOK.TITLE)
+ .over().partitionBy(BOOK.AUTHOR_ID))
+ .from(BOOK)
+
+
+ Window functions created from Oracle's FIRST and LAST aggregate functions
+
+ In the previous chapter about , we have seen the concept of "FIRST and LAST aggregate functions". These functions have a window function / analytical function variant, as well. For example:
+
+
+
+SUM(BOOK.AMOUNT_SOLD)
+ KEEP(DENSE_RANK FIRST ORDER BY BOOK.AUTHOR_ID)
+ OVER(PARTITION BY 1)
+sum(BOOK.AMOUNT_SOLD)
+ .keepDenseRankFirstOrderBy(BOOK.AUTHOR_ID)
+ .over().partitionByOne()
+
+
+
+ Window functions created from user-defined aggregate functions
+
+ User-defined aggregate functions also implement , hence they can also be transformed into window functions using over(). This is supported by Oracle in particular. See the manual's section about for more details.
+
+