A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls below:

Window function calls | BigQuery

Skip to main content Window function calls

Stay organized with collections Save and categorize content based on your preferences.

A window function, also known as an analytic function, computes values over a group of rows and returns a single result for each row. This is different from an aggregate function, which returns a single result for a group of rows.

A window function includes an OVER clause, which defines a window of rows around the row being evaluated. For each row, the window function result is computed using the selected window of rows as input, possibly doing aggregation.

With window functions you can compute moving averages, rank items, calculate cumulative sums, and perform other analyses.

Window function syntax
function_name ( [ argument_list ] ) OVER over_clause

over_clause:
  { named_window | ( [ window_specification ] ) }

window_specification:
  [ named_window ]
  [ PARTITION BY partition_expression [, ...] ]
  [ ORDER BY expression [ { ASC | DESC }  ] [, ...] ]
  [ window_frame_clause ]

window_frame_clause:
  { rows_range } { frame_start | frame_between }

rows_range:
  { ROWS | RANGE }

Description

A window function computes results over a group of rows. You can use the following syntax to build a window function:

Notes

A window function can appear as a scalar expression operand in the following places in the query:

A window function can't refer to another window function in its argument list or its OVER clause, even indirectly through an alias.

A window function is evaluated after aggregation. For example, the GROUP BY clause and non-window aggregate functions are evaluated first. Because aggregate functions are evaluated before window functions, aggregate functions can be used as input operands to window functions.

Returns

A single result for each row in the input.

Defining the OVER clause
function_name ( [ argument_list ] ) OVER over_clause

over_clause:
  { named_window | ( [ window_specification ] ) }

Description

The OVER clause references a window that defines a group of rows in a table upon which to use a window function. You can provide a named_window that is defined in your query, or you can define the specifications for a new window.

Notes

If neither a named window nor window specification is provided, all input rows are included in the window for every row.

Examples using the OVER clause

These queries use window specifications:

These queries use a named window:

Defining the window specification
window_specification:
  [ named_window ]
  [ PARTITION BY partition_expression [, ...] ]
  [ ORDER BY expression [ { ASC | DESC } ] [, ...] ]
  [ window_frame_clause ]

Description

Defines the specifications for the window.

Important: If you use a named window, special rules apply to PARTITION BY, ORDER BY, and window_frame_clause. See Rules for using a named window in the window specification.

Notes

If neither the ORDER BY clause nor window frame clause are present, the window frame includes all rows in that partition.

For aggregate analytic functions, if the ORDER BY clause is present but the window frame clause isn't, the following window frame clause is used by default:

RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

For example, the following queries are equivalent:

SELECT book, LAST_VALUE(book)
  OVER (ORDER BY year)
FROM Library
SELECT book, LAST_VALUE(book)
  OVER (
    ORDER BY year
    RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM Library

Rules for using a named window in the window specification

If you use a named window in your window specifications, these rules apply:

Examples using the window specification

These queries define partitions in a window function:

These queries include a named window in a window specification:

These queries define how rows are ordered in a partition:

Defining the window frame clause
window_frame_clause:
  { rows_range } { frame_start | frame_between }

rows_range:
  { ROWS | RANGE }

frame_between:
  {
    BETWEEN  unbounded_preceding AND frame_end_a
    | BETWEEN numeric_preceding AND frame_end_a
    | BETWEEN current_row AND frame_end_b
    | BETWEEN numeric_following AND frame_end_c
  }

frame_start:
  { unbounded_preceding | numeric_preceding | [ current_row ] }

frame_end_a:
  { numeric_preceding | current_row | numeric_following | unbounded_following }

frame_end_b:
  { current_row | numeric_following | unbounded_following }

frame_end_c:
  { numeric_following | unbounded_following }

unbounded_preceding:
  UNBOUNDED PRECEDING

numeric_preceding:
  numeric_expression PRECEDING

unbounded_following:
  UNBOUNDED FOLLOWING

numeric_following:
  numeric_expression FOLLOWING

current_row:
  CURRENT ROW

The window frame clause defines the window frame around the current row within a partition, over which the window function is evaluated. Only aggregate analytic functions can use a window frame clause.

Notes

If a boundary extends beyond the beginning or end of a partition, the window frame will only include rows from within that partition.

You can't use a window frame clause with some navigation functions and numbering functions, such as RANK().

Examples using the window frame clause

These queries compute values with ROWS:

These queries compute values with RANGE:

These queries compute values with a partially or fully unbound window:

These queries compute values with numeric boundaries:

These queries compute values with the current row as a boundary:

Referencing a named window
SELECT query_expr,
  function_name ( [ argument_list ] ) OVER over_clause
FROM from_item
WINDOW named_window_expression [, ...]

over_clause:
  { named_window | ( [ window_specification ] ) }

window_specification:
  [ named_window ]
  [ PARTITION BY partition_expression [, ...] ]
  [ ORDER BY expression [ { ASC | DESC } ] [, ...] ]
  [ window_frame_clause ]

named_window_expression:
  named_window AS { named_window | ( [ window_specification ] ) }

A named window represents a group of rows in a table upon which to use an window function. A named window is defined in the WINDOW clause, and referenced in a window function's OVER clause. In an OVER clause, a named window can appear either by itself or embedded within a window specification.

Examples

Filtering results with the QUALIFY clause

The QUALIFY clause can be used to filter the results of a window function. For more information and examples, see the QUALIFY clause.

Window function examples

In these examples, the highlighted item is the current row. The bolded items are the rows that are included in the analysis.

Common tables used in examples

The following tables are used in the subsequent aggregate analytic query examples: Produce, Employees, and Farm.

Produce table

Some examples reference a table called Produce:

WITH Produce AS
 (SELECT 'kale' as item, 23 as purchases, 'vegetable' as category
  UNION ALL SELECT 'banana', 2, 'fruit'
  UNION ALL SELECT 'cabbage', 9, 'vegetable'
  UNION ALL SELECT 'apple', 8, 'fruit'
  UNION ALL SELECT 'leek', 2, 'vegetable'
  UNION ALL SELECT 'lettuce', 10, 'vegetable')
SELECT * FROM Produce

/*-------------------------------------*
 | item      | category   | purchases  |
 +-------------------------------------+
 | kale      | vegetable  | 23         |
 | banana    | fruit      | 2          |
 | cabbage   | vegetable  | 9          |
 | apple     | fruit      | 8          |
 | leek      | vegetable  | 2          |
 | lettuce   | vegetable  | 10         |
 *-------------------------------------*/
Employees table

Some examples reference a table called Employees:

WITH Employees AS
 (SELECT 'Isabella' as name, 2 as department, DATE(1997, 09, 28) as start_date
  UNION ALL SELECT 'Anthony', 1, DATE(1995, 11, 29)
  UNION ALL SELECT 'Daniel', 2, DATE(2004, 06, 24)
  UNION ALL SELECT 'Andrew', 1, DATE(1999, 01, 23)
  UNION ALL SELECT 'Jacob', 1, DATE(1990, 07, 11)
  UNION ALL SELECT 'Jose', 2, DATE(2013, 03, 17))
SELECT * FROM Employees

/*-------------------------------------*
 | name      | department | start_date |
 +-------------------------------------+
 | Isabella  | 2          | 1997-09-28 |
 | Anthony   | 1          | 1995-11-29 |
 | Daniel    | 2          | 2004-06-24 |
 | Andrew    | 1          | 1999-01-23 |
 | Jacob     | 1          | 1990-07-11 |
 | Jose      | 2          | 2013-03-17 |
 *-------------------------------------*/
Farm table

Some examples reference a table called Farm:

WITH Farm AS
 (SELECT 'cat' as animal, 23 as population, 'mammal' as category
  UNION ALL SELECT 'duck', 3, 'bird'
  UNION ALL SELECT 'dog', 2, 'mammal'
  UNION ALL SELECT 'goose', 1, 'bird'
  UNION ALL SELECT 'ox', 2, 'mammal'
  UNION ALL SELECT 'goat', 2, 'mammal')
SELECT * FROM Farm

/*-------------------------------------*
 | animal    | category   | population |
 +-------------------------------------+
 | cat       | mammal     | 23         |
 | duck      | bird       | 3          |
 | dog       | mammal     | 2          |
 | goose     | bird       | 1          |
 | ox        | mammal     | 2          |
 | goat      | mammal     | 2          |
 *-------------------------------------*/
Compute a grand total

This computes a grand total for all items in the Produce table.

SELECT item, purchases, category, SUM(purchases)
  OVER () AS total_purchases
FROM Produce

/*-------------------------------------------------------*
 | item      | purchases  | category   | total_purchases |
 +-------------------------------------------------------+
 | banana    | 2          | fruit      | 54              |
 | leek      | 2          | vegetable  | 54              |
 | apple     | 8          | fruit      | 54              |
 | cabbage   | 9          | vegetable  | 54              |
 | lettuce   | 10         | vegetable  | 54              |
 | kale      | 23         | vegetable  | 54              |
 *-------------------------------------------------------*/
Compute a subtotal

This computes a subtotal for each category in the Produce table.

SELECT item, purchases, category, SUM(purchases)
  OVER (
    PARTITION BY category
    ORDER BY purchases
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) AS total_purchases
FROM Produce

/*-------------------------------------------------------*
 | item      | purchases  | category   | total_purchases |
 +-------------------------------------------------------+
 | banana    | 2          | fruit      | 10              |
 | apple     | 8          | fruit      | 10              |
 | leek      | 2          | vegetable  | 44              |
 | cabbage   | 9          | vegetable  | 44              |
 | lettuce   | 10         | vegetable  | 44              |
 | kale      | 23         | vegetable  | 44              |
 *-------------------------------------------------------*/
Compute a cumulative sum

This computes a cumulative sum for each category in the Produce table. The sum is computed with respect to the order defined using the ORDER BY clause.

SELECT item, purchases, category, SUM(purchases)
  OVER (
    PARTITION BY category
    ORDER BY purchases
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS total_purchases
FROM Produce

/*-------------------------------------------------------*
 | item      | purchases  | category   | total_purchases |
 +-------------------------------------------------------+
 | banana    | 2          | fruit      | 2               |
 | apple     | 8          | fruit      | 10              |
 | leek      | 2          | vegetable  | 2               |
 | cabbage   | 9          | vegetable  | 11              |
 | lettuce   | 10         | vegetable  | 21              |
 | kale      | 23         | vegetable  | 44              |
 *-------------------------------------------------------*/

This does the same thing as the preceding example. You don't have to add CURRENT ROW as a boundary unless you would like to for readability.

SELECT item, purchases, category, SUM(purchases)
  OVER (
    PARTITION BY category
    ORDER BY purchases
    ROWS UNBOUNDED PRECEDING
  ) AS total_purchases
FROM Produce

In this example, all items in the Produce table are included in the partition. Only preceding rows are analyzed. The analysis starts two rows prior to the current row in the partition.

SELECT item, purchases, category, SUM(purchases)
  OVER (
    ORDER BY purchases
    ROWS BETWEEN UNBOUNDED PRECEDING AND 2 PRECEDING
  ) AS total_purchases
FROM Produce;

/*-------------------------------------------------------*
 | item      | purchases  | category   | total_purchases |
 +-------------------------------------------------------+
 | banana    | 2          | fruit      | NULL            |
 | leek      | 2          | vegetable  | NULL            |
 | apple     | 8          | fruit      | 2               |
 | cabbage   | 9          | vegetable  | 4               |
 | lettuce   | 10         | vegetable  | 12              |
 | kale      | 23         | vegetable  | 21              |
 *-------------------------------------------------------*/
Compute a moving average

This computes a moving average in the Produce table. The lower boundary is 1 row before the current row. The upper boundary is 1 row after the current row.

SELECT item, purchases, category, AVG(purchases)
  OVER (
    ORDER BY purchases
    ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) AS avg_purchases
FROM Produce

/*-------------------------------------------------------*
 | item      | purchases  | category   | avg_purchases   |
 +-------------------------------------------------------+
 | banana    | 2          | fruit      | 2               |
 | leek      | 2          | vegetable  | 4               |
 | apple     | 8          | fruit      | 6.33333         |
 | cabbage   | 9          | vegetable  | 9               |
 | lettuce   | 10         | vegetable  | 14              |
 | kale      | 23         | vegetable  | 16.5            |
 *-------------------------------------------------------*/
Compute the number of items within a range

This example gets the number of animals that have a similar population count in the Farm table.

SELECT animal, population, category, COUNT(*)
  OVER (
    ORDER BY population
    RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) AS similar_population
FROM Farm;

/*----------------------------------------------------------*
 | animal    | population | category   | similar_population |
 +----------------------------------------------------------+
 | goose     | 1          | bird       | 4                  |
 | dog       | 2          | mammal     | 5                  |
 | ox        | 2          | mammal     | 5                  |
 | goat      | 2          | mammal     | 5                  |
 | duck      | 3          | bird       | 4                  |
 | cat       | 23         | mammal     | 1                  |
 *----------------------------------------------------------*/
Get the most popular item in each category

This example gets the most popular item in each category. It defines how rows in a window are partitioned and ordered in each partition. The Produce table is referenced.

SELECT item, purchases, category, LAST_VALUE(item)
  OVER (
    PARTITION BY category
    ORDER BY purchases
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) AS most_popular
FROM Produce

/*----------------------------------------------------*
 | item      | purchases  | category   | most_popular |
 +----------------------------------------------------+
 | banana    | 2          | fruit      | apple        |
 | apple     | 8          | fruit      | apple        |
 | leek      | 2          | vegetable  | kale         |
 | cabbage   | 9          | vegetable  | kale         |
 | lettuce   | 10         | vegetable  | kale         |
 | kale      | 23         | vegetable  | kale         |
 *----------------------------------------------------*/
Get the last value in a range

This example gets the most popular item in a specific window frame, using the Produce table. The window frame analyzes up to three rows at a time. Take a close look at the most_popular column for vegetables. Instead of getting the most popular item in a specific category, it gets the most popular item in a specific range in that category.

SELECT item, purchases, category, LAST_VALUE(item)
  OVER (
    PARTITION BY category
    ORDER BY purchases
    ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) AS most_popular
FROM Produce

/*----------------------------------------------------*
 | item      | purchases  | category   | most_popular |
 +----------------------------------------------------+
 | banana    | 2          | fruit      | apple        |
 | apple     | 8          | fruit      | apple        |
 | leek      | 2          | vegetable  | cabbage      |
 | cabbage   | 9          | vegetable  | lettuce      |
 | lettuce   | 10         | vegetable  | kale         |
 | kale      | 23         | vegetable  | kale         |
 *----------------------------------------------------*/

This example returns the same results as the preceding example, but it includes a named window called item_window. Some of the window specifications are defined directly in the OVER clause and some are defined in the named window.

SELECT item, purchases, category, LAST_VALUE(item)
  OVER (
    item_window
    ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
  ) AS most_popular
FROM Produce
WINDOW item_window AS (
  PARTITION BY category
  ORDER BY purchases)
Compute rank

This example calculates the rank of each employee within their department, based on their start date. The window specification is defined directly in the OVER clause. The Employees table is referenced.

SELECT name, department, start_date,
  RANK() OVER (PARTITION BY department ORDER BY start_date) AS rank
FROM Employees;

/*--------------------------------------------*
 | name      | department | start_date | rank |
 +--------------------------------------------+
 | Jacob     | 1          | 1990-07-11 | 1    |
 | Anthony   | 1          | 1995-11-29 | 2    |
 | Andrew    | 1          | 1999-01-23 | 3    |
 | Isabella  | 2          | 1997-09-28 | 1    |
 | Daniel    | 2          | 2004-06-24 | 2    |
 | Jose      | 2          | 2013-03-17 | 3    |
 *--------------------------------------------*/
Use a named window in a window frame clause

You can define some of your logic in a named window and some of it in a window frame clause. This logic is combined. Here is an example, using the Produce table.

SELECT item, purchases, category, LAST_VALUE(item)
  OVER (item_window) AS most_popular
FROM Produce
WINDOW item_window AS (
  PARTITION BY category
  ORDER BY purchases
  ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING)

/*-------------------------------------------------------*
 | item      | purchases  | category   | most_popular    |
 +-------------------------------------------------------+
 | banana    | 2          | fruit      | apple           |
 | apple     | 8          | fruit      | apple           |
 | leek      | 2          | vegetable  | lettuce         |
 | cabbage   | 9          | vegetable  | kale            |
 | lettuce   | 10         | vegetable  | kale            |
 | kale      | 23         | vegetable  | kale            |
 *-------------------------------------------------------*/

You can also get the previous results with these examples:

SELECT item, purchases, category, LAST_VALUE(item)
  OVER (item_window) AS most_popular
FROM Produce
WINDOW
  a AS (PARTITION BY category),
  b AS (a ORDER BY purchases),
  c AS (b ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING),
  item_window AS (c)
SELECT item, purchases, category, LAST_VALUE(item)
  OVER (item_window ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) AS most_popular
FROM Produce
WINDOW
  a AS (PARTITION BY category),
  b AS (a ORDER BY purchases),
  item_window AS (b)

The following example produces an error because a window frame clause has been defined twice:

SELECT item, purchases, category, LAST_VALUE(item)
  OVER (
    item_window
    ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
    ) AS most_popular
FROM Produce
WINDOW item_window AS (
  ORDER BY purchases
  ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING)

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-07-02 UTC.

[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-07-02 UTC."],[[["Window functions calculate results over a group of rows, returning a single result for each row, unlike aggregate functions which return a single result for the entire group."],["The `OVER` clause is a key component of window functions, defining the window of rows around the row being evaluated and determining which rows are used as input for calculations, possibly including aggregation."],["Window functions offer the ability to compute moving averages, rank items, calculate cumulative sums, and perform other analyses by defining how rows are partitioned and ordered within a window."],["The window specification allows for the use of `PARTITION BY` to divide rows into independent groups, `ORDER BY` to define row order within partitions, and `window_frame_clause` to set the boundaries of the window frame."],["Named windows can be created and referenced to simplify window function syntax, allowing specifications to be reused and extended across multiple window functions, enhancing query readability and maintainability."]]],[]]


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4