Range functions Stay organized with collections Save and categorize content based on your preferences.
GoogleSQL for BigQuery supports the following range functions.
Function list
| Name | Summary |
|---|---|
APPENDS | Returns all rows appended to a table for a given time range. For more information, seeTime series functions. |
CHANGES | Returns all rows that have changed in a table for a given time range. For more information, seeTime series functions. |
GENERATE_RANGE_ARRAY | Splits a range into an array of subranges. |
RANGE | Constructs a range ofDATE,DATETIME, orTIMESTAMP values. |
RANGE_BUCKET | Scans through a sorted array and returns the 0-based position of a point's upper bound. For more information, seeMathematical functions. |
RANGE_CONTAINS | Signature 1: Checks if one range is in another range. Signature 2: Checks if a value is in a range. |
RANGE_END | Gets the upper bound of a range. |
RANGE_INTERSECT | Gets a segment of two ranges that intersect. |
RANGE_OVERLAPS | Checks if two ranges overlap. |
RANGE_SESSIONIZE | Produces a table of sessionized ranges. |
RANGE_START | Gets the lower bound of a range. |
GENERATE_RANGE_ARRAY
GENERATE_RANGE_ARRAY(range_to_split,step_interval)GENERATE_RANGE_ARRAY(range_to_split,step_interval,include_last_partial_range)Description
Splits a range into an array of subranges.
Definitions
range_to_split: TheRANGE<T>value to split.step_interval: TheINTERVALvalue, which determines the maximum size ofeach subrange in the resulting array. Aninterval single date and time partis supported, but an interval range of date and time parts isn't.If
range_to_splitisRANGE<DATE>, these intervaldate parts are supported:YEARtoDAY.If
range_to_splitisRANGE<DATETIME>, these intervaldate and time parts are supported:YEARtoSECOND.If
range_to_splitisRANGE<TIMESTAMP>, these intervaldate and time parts are supported:DAYtoSECOND.
include_last_partial_range: ABOOLvalue, which determines whether ornot to include the last subrange if it's a partial subrange.If this argument isn't specified, the default value isTRUE.TRUE(default): The last subrange is included, even if it'ssmaller thanstep_interval.FALSE: Exclude the last subrange if it's smaller thanstep_interval.
Details
ReturnsNULL if any input isNULL.
Return type
ARRAY<RANGE<T>>
Examples
In the following example, a date range between2020-01-01 and2020-01-06is split into an array of subranges that are one day long. There areno partial ranges.
SELECTGENERATE_RANGE_ARRAY(RANGE(DATE'2020-01-01',DATE'2020-01-06'),INTERVAL1DAY)ASresults;/*----------------------------+ | results | +----------------------------+ | [ | | [2020-01-01, 2020-01-02), | | [2020-01-02, 2020-01-03), | | [2020-01-03, 2020-01-04), | | [2020-01-04, 2020-01-05), | | [2020-01-05, 2020-01-06), | | ] | +----------------------------*/In the following examples, a date range between2020-01-01 and2020-01-06is split into an array of subranges that are two days long. The final subrangeis smaller than two days:
SELECTGENERATE_RANGE_ARRAY(RANGE(DATE'2020-01-01',DATE'2020-01-06'),INTERVAL2DAY)ASresults;/*----------------------------+ | results | +----------------------------+ | [ | | [2020-01-01, 2020-01-03), | | [2020-01-03, 2020-01-05), | | [2020-01-05, 2020-01-06) | | ] | +----------------------------*/SELECTGENERATE_RANGE_ARRAY(RANGE(DATE'2020-01-01',DATE'2020-01-06'),INTERVAL2DAY,TRUE)ASresults;/*----------------------------+ | results | +----------------------------+ | [ | | [2020-01-01, 2020-01-03), | | [2020-01-03, 2020-01-05), | | [2020-01-05, 2020-01-06) | | ] | +----------------------------*/In the following example, a date range between2020-01-01 and2020-01-06is split into an array of subranges that are two days long, but the finalsubrange is excluded because it's smaller than two days:
SELECTGENERATE_RANGE_ARRAY(RANGE(DATE'2020-01-01',DATE'2020-01-06'),INTERVAL2DAY,FALSE)ASresults;/*----------------------------+ | results | +----------------------------+ | [ | | [2020-01-01, 2020-01-03), | | [2020-01-03, 2020-01-05) | | ] | +----------------------------*/RANGE
RANGE(lower_bound,upper_bound)Description
Constructs a range ofDATE,DATETIME, orTIMESTAMP values.
Definitions
lower_bound: The range starts from this value. This can be aDATE,DATETIME, orTIMESTAMPvalue. If this value isNULL, the rangedoesn't include a lower bound.upper_bound: The range ends before this value. This can be aDATE,DATETIME, orTIMESTAMPvalue. If this value isNULL, the rangedoesn't include an upper bound.
Details
lower_bound andupper_bound must be of the same data type.
Produces an error iflower_bound is greater than or equal toupper_bound.To returnNULL instead, add theSAFE. prefix to the function name.
Return type
RANGE<T>, whereT is the same data type as the input.
Examples
The following query constructs a date range:
SELECTRANGE(DATE'2022-12-01',DATE'2022-12-31')ASresults;/*--------------------------+ | results | +--------------------------+ | [2022-12-01, 2022-12-31) | +--------------------------*/The following query constructs a datetime range:
SELECTRANGE(DATETIME'2022-10-01 14:53:27',DATETIME'2022-10-01 16:00:00')ASresults;/*---------------------------------------------+ | results | +---------------------------------------------+ | [2022-10-01T14:53:27, 2022-10-01T16:00:00) | +---------------------------------------------*/The following query constructs a timestamp range:
SELECTRANGE(TIMESTAMP'2022-10-01 14:53:27 America/Los_Angeles',TIMESTAMP'2022-10-01 16:00:00 America/Los_Angeles')ASresults;-- Results depend upon where this query was executed./*------------------------------------------------------------------+ | results | +------------------------------------------------------------------+ | [2022-10-01 21:53:27.000000 UTC, 2022-10-01 23:00:00.000000 UTC) | +------------------------------------------------------------------*/The following query constructs a date range with no lower bound:
SELECTRANGE(NULL,DATE'2022-12-31')ASresults;/*-------------------------+ | results | +-------------------------+ | [UNBOUNDED, 2022-12-31) | +-------------------------*/The following query constructs a date range with no upper bound:
SELECTRANGE(DATE'2022-10-01',NULL)ASresults;/*--------------------------+ | results | +--------------------------+ | [2022-10-01, UNBOUNDED) | +--------------------------*/RANGE_CONTAINS
- Signature 1: Checks if every value in one range isin another range.
- Signature 2: Checks if a value is in a range.
Signature 1
RANGE_CONTAINS(outer_range,inner_range)Description
Checks if the inner range is in the outer range.
Definitions
outer_range: TheRANGE<T>value to search within.inner_range: TheRANGE<T>value to search for inouter_range.
Details
ReturnsTRUE ifinner_range exists inouter_range.Otherwise, returnsFALSE.
T must be of the same type for all inputs.
Return type
BOOL
Examples
In the following query, the inner range is in the outer range:
SELECTRANGE_CONTAINS(RANGE<DATE>'[2022-01-01, 2023-01-01)',RANGE<DATE>'[2022-04-01, 2022-07-01)')ASresults;/*---------+ | results | +---------+ | TRUE | +---------*/In the following query, the inner range isn't in the outer range:
SELECTRANGE_CONTAINS(RANGE<DATE>'[2022-01-01, 2023-01-01)',RANGE<DATE>'[2023-01-01, 2023-04-01)')ASresults;/*---------+ | results | +---------+ | FALSE | +---------*/Signature 2
RANGE_CONTAINS(range_to_search,value_to_find)Description
Checks if a value is in a range.
Definitions
range_to_search: TheRANGE<T>value to search within.value_to_find: The value to search for inrange_to_search.
Details
ReturnsTRUE ifvalue_to_find exists inrange_to_search.Otherwise, returnsFALSE.
The data type forvalue_to_find must be the same data type asTinrange_to_search.
Return type
BOOL
Examples
In the following query, the value2022-04-01 is found in the range[2022-01-01, 2023-01-01):
SELECTRANGE_CONTAINS(RANGE<DATE>'[2022-01-01, 2023-01-01)',DATE'2022-04-01')ASresults;/*---------+ | results | +---------+ | TRUE | +---------*/In the following query, the value2023-04-01 isn't found in the range[2022-01-01, 2023-01-01):
SELECTRANGE_CONTAINS(RANGE<DATE>'[2022-01-01, 2023-01-01)',DATE'2023-04-01')ASresults;/*---------+ | results | +---------+ | FALSE | +---------*/RANGE_END
RANGE_END(range_to_check)Description
Gets the upper bound of a range.
Definitions
range_to_check: TheRANGE<T>value.
Details
ReturnsNULL if the upper bound inrange_value isUNBOUNDED.
ReturnsNULL ifrange_to_check isNULL.
Return type
T inrange_value
Examples
In the following query, the upper bound of the range is retrieved:
SELECTRANGE_END(RANGE<DATE>'[2022-12-01, 2022-12-31)')ASresults;/*------------+ | results | +------------+ | 2022-12-31 | +------------*/In the following query, the upper bound of the range is unbounded, soNULL is returned:
SELECTRANGE_END(RANGE<DATE>'[2022-12-01, UNBOUNDED)')ASresults;/*------------+ | results | +------------+ | NULL | +------------*/RANGE_INTERSECT
RANGE_INTERSECT(range_a,range_b)Description
Gets a segment of two ranges that intersect.
Definitions
range_a: The firstRANGE<T>value.range_b: The secondRANGE<T>value.
Details
ReturnsNULL if any input isNULL.
Produces an error ifrange_a andrange_b don't overlap. To returnNULL instead, add theSAFE. prefix to the function name.
T must be of the same type for all inputs.
Return type
RANGE<T>
Examples
SELECTRANGE_INTERSECT(RANGE<DATE>'[2022-02-01, 2022-09-01)',RANGE<DATE>'[2021-06-15, 2022-04-15)')ASresults;/*--------------------------+ | results | +--------------------------+ | [2022-02-01, 2022-04-15) | +--------------------------*/SELECTRANGE_INTERSECT(RANGE<DATE>'[2022-02-01, UNBOUNDED)',RANGE<DATE>'[2021-06-15, 2022-04-15)')ASresults;/*--------------------------+ | results | +--------------------------+ | [2022-02-01, 2022-04-15) | +--------------------------*/SELECTRANGE_INTERSECT(RANGE<DATE>'[2022-02-01, UNBOUNDED)',RANGE<DATE>'[2021-06-15, UNBOUNDED)')ASresults;/*-------------------------+ | results | +-------------------------+ | [2022-02-01, UNBOUNDED) | +-------------------------*/RANGE_OVERLAPS
RANGE_OVERLAPS(range_a,range_b)Description
Checks if two ranges overlap.
Definitions
range_a: The firstRANGE<T>value.range_b: The secondRANGE<T>value.
Details
ReturnsTRUE if a part ofrange_a intersects withrange_b, otherwisereturnsFALSE.
T must be of the same type for all inputs.
To get the part of the range that overlaps, use theRANGE_INTERSECT function.
Return type
BOOL
Examples
In the following query, the first and second ranges overlap between2022-02-01 and2022-04-15:
SELECTRANGE_OVERLAPS(RANGE<DATE>'[2022-02-01, 2022-09-01)',RANGE<DATE>'[2021-06-15, 2022-04-15)')ASresults;/*---------+ | results | +---------+ | TRUE | +---------*/In the following query, the first and second ranges don't overlap:
SELECTRANGE_OVERLAPS(RANGE<DATE>'[2020-02-01, 2020-09-01)',RANGE<DATE>'[2021-06-15, 2022-04-15)')ASresults;/*---------+ | results | +---------+ | FALSE | +---------*/In the following query, the first and second ranges overlap between2022-02-01 andUNBOUNDED:
SELECTRANGE_OVERLAPS(RANGE<DATE>'[2022-02-01, UNBOUNDED)',RANGE<DATE>'[2021-06-15, UNBOUNDED)')ASresults;/*---------+ | results | +---------+ | TRUE | +---------*/RANGE_SESSIONIZE
RANGE_SESSIONIZE(TABLEtable_name,range_column,partitioning_columns)RANGE_SESSIONIZE(TABLEtable_name,range_column,partitioning_columns,sessionize_option)Description
Produces a table of sessionized ranges.
Definitions
table_name: A table expression that represents the name of the table toconstruct. This can represent any relation withrange_column.range_column: ASTRINGliteral that indicates whichRANGEcolumnin a table contains the data to sessionize.partitioning_columns: AnARRAY<STRING>literal that indicates whichcolumns should partition the data before the data is sessionized.sessionize_option: ASTRINGvalue that describes how order-adjacentranges are sessionized. Your choices are as follows:MEETS(default): Ranges that meet or overlap are sessionized.OVERLAPS: Only a range that's overlapped by another range issessionized.
If this argument isn't provided,
MEETSis used by default.
Details
This function produces a table that includes all columns in theinput table and an additionalRANGE column calledsession_range, which indicates the start and end of a session. Thestart and end of each session is determined by thesessionize_optionargument.
Return type
TABLE
Examples
The examples in this section reference the following table calledmy_sessionized_range_table in a dataset calledmydataset:
INSERTmydataset.my_sessionized_range_table(emp_id,dept_id,duration)VALUES(10,1000,RANGE<DATE>'[2010-01-10, 2010-03-10)'),(10,2000,RANGE<DATE>'[2010-03-10, 2010-07-15)'),(10,2000,RANGE<DATE>'[2010-06-15, 2010-08-18)'),(20,2000,RANGE<DATE>'[2010-03-10, 2010-07-20)'),(20,1000,RANGE<DATE>'[2020-05-10, 2020-09-20)');SELECT*FROMmydataset.my_sessionized_range_tableORDERBYemp_id;/*--------+---------+--------------------------+ | emp_id | dept_id | duration | +--------+---------+--------------------------+ | 10 | 1000 | [2010-01-10, 2010-03-10) | | 10 | 2000 | [2010-03-10, 2010-07-15) | | 10 | 2000 | [2010-06-15, 2010-08-18) | | 20 | 2000 | [2010-03-10, 2010-07-20) | | 20 | 1000 | [2020-05-10, 2020-09-20) | +--------+---------+--------------------------*/In the following query, a table of sessionized data is produced formy_sessionized_range_table, and only ranges that meet or overlap aresessionized:
SELECTemp_id,duration,session_rangeFROMRANGE_SESSIONIZE(TABLEmydataset.my_sessionized_range_table,'duration',['emp_id'])ORDERBYemp_id;/*--------+--------------------------+--------------------------+ | emp_id | duration | session_range | +--------+--------------------------+--------------------------+ | 10 | [2010-01-10, 2010-03-10) | [2010-01-10, 2010-08-18) | | 10 | [2010-03-10, 2010-07-15) | [2010-01-10, 2010-08-18) | | 10 | [2010-06-15, 2010-08-18) | [2010-01-10, 2010-08-18) | | 20 | [2010-03-10, 2010-07-20) | [2010-03-10, 2010-07-20) | | 20 | [2020-05-10, 2020-09-20) | [2020-05-10, 2020-09-20) | +--------+-----------------------------------------------------*/In the following query, a table of sessionized data is produced formy_sessionized_range_table, and only a range that's overlapped by anotherrange is sessionized:
SELECTemp_id,duration,session_rangeFROMRANGE_SESSIONIZE(TABLEmydataset.my_sessionized_range_table,'duration',['emp_id'],'OVERLAPS')ORDERBYemp_id;/*--------+--------------------------+--------------------------+ | emp_id | duration | session_range | +--------+--------------------------+--------------------------+ | 10 | [2010-03-10, 2010-07-15) | [2010-03-10, 2010-08-18) | | 10 | [2010-06-15, 2010-08-18) | [2010-03-10, 2010-08-18) | | 10 | [2010-01-10, 2010-03-10) | [2010-01-10, 2010-03-10) | | 20 | [2020-05-10, 2020-09-20) | [2020-05-10, 2020-09-20) | | 20 | [2010-03-10, 2010-07-20) | [2010-03-10, 2010-07-20) | +--------+-----------------------------------------------------*/If you need to normalize sessionized data, you can use a query similar to thefollowing:
SELECTemp_id,session_rangeASnormalizedFROM(SELECTemp_id,session_rangeFROMRANGE_SESSIONIZE(TABLEmydataset.my_sessionized_range_table,'duration',['emp_id'],'MEETS'))GROUPBYemp_id,normalized;/*--------+--------------------------+ | emp_id | normalized | +--------+--------------------------+ | 20 | [2010-03-10, 2010-07-20) | | 10 | [2010-01-10, 2010-08-18) | | 20 | [2020-05-10, 2020-09-20) | +--------+--------------------------*/RANGE_START
RANGE_START(range_to_check)Description
Gets the lower bound of a range.
Definitions
range_to_check: TheRANGE<T>value.
Details
ReturnsNULL if the lower bound ofrange_value isUNBOUNDED.
ReturnsNULL ifrange_to_check isNULL.
Return type
T inrange_value
Examples
In the following query, the lower bound of the range is retrieved:
SELECTRANGE_START(RANGE<DATE>'[2022-12-01, 2022-12-31)')ASresults;/*------------+ | results | +------------+ | 2022-12-01 | +------------*/In the following query, the lower bound of the range is unbounded, soNULL is returned:
SELECTRANGE_START(RANGE<DATE>'[UNBOUNDED, 2022-12-31)')ASresults;/*------------+ | results | +------------+ | NULL | +------------*/Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-11-24 UTC.