All window functions utilise a set of clauses specific for them, some of which are mandatory while others are optional.
When it comes to required ones, there is the OVER
clause, which defines a window or user-specified set of rows within a query result set. It is a mandatory element of window functions, defining the window specification and differentiating them from other SQL functions.
The syntax for this clause looks as follows:
where, the PARTITION BY
clause is a list of expressions
interpreted in much the same fashion as the elements of a GROUP BY
clause, with major exception that they are always simple expressions and never the name or number of an output column. Another difference is that these expressions can contain aggregate function calls, which are not allowed in a regular GROUP BY
clause (they are allowed here because windowing occurs after grouping and aggregation)
[ PARTITION BY expression [, ...] ]
(optional window partition)
The ORDER BY
clause used in the OVER
clause above is a list of expressions
interpreted in much the same fashion as the elements of a statement-level ORDER BY
clause, except that the expressions are always taken as simple expressions and never the name or number of an output column.
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
(optional window ordering)
In terms of window functions’ optional clauses, there is the WINDOW
clause that defines one or more named window specification, as a window_name
and window_definition
pair.
The syntax for this clause looks as follows:
where window_name
is a name that can be referenced from the OVER
clauses or subsequent window definition
. There are a few important things to keep in mind here:
window_definition
may use an existing_window_name
to refer to a previous window_definition
in the WINDOW
clause, but the previous window_definition
must not specify a frame
clausewindow_definition
copies the PARTITION BY
clause and ORDER BY
clause from previous window_definition
, but it cannot specify its own PARTION BY
clause, and can specify an ORDER BY
clause if the previous window_definition
does not have one.[ existing_window_name ] [ PARTITION BY clause ] [ ORDER BY clause ] [ frame clause ]
(all arguments are optional)
window_definition
without arguments defines a window with all rows without partition and orderingThe frame
clause referenced above defines the window frame for window functions that depend on the frame (not all do).
The window frame is a set of related rows for each row of the query (called the current row).
{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]
frame
clause of the window specification is limited to the ROWS
clause without frame exclusion
oneThere are a couple of things, to keep in mind here:
frame_start
and frame_end
can be one of: UNBOUNDED PRECEDING
, offset PRECEDING
, CURRENT ROW
, offset FOLLOWING
, UNBOUNDED FOLLOWING
.frame_end
is omitted it defaults to CURRENT ROW
. Restrictions here are as follows:
frame_start
cannot be UNBOUNDED FOLLOWING
frame_end
cannot be UNBOUNDED PRECEDING
frame_end
choice cannot appear earlier in the above list of frame_start
and frame_end
options than the frame_start
choice doesIn ROWS
mode, CURRENT ROW
means that the frame starts or ends with the current row, the offset is an integer indicating that the frame starts or ends that many rows before or after the current row.
ROWS
mode can produce unpredictable results if the ORDER BY
ordering does not order the rows uniquelyFor the needs of this section, we will create the winsales
table that stores details about some sales transactions:
In this example, we will focus on executing a window function with the OVER
clause, window definition and PARTITION BY
and ORDER BY
clauses:
Here’s the output for the above code:
In this example, we will focus on executing a window function with the OVER
clause, window name and PARITION BY
and ORDER BY
clauses:
When executing the code above, we will get the following output: