Conheça a sintaxe das funções de janela e saiba como utilizá-las em consultas analíticas do SLS.
Introdução
Diferentemente das funções de agregação, que consolidam linhas em um único resultado, as funções de janela calculam um resultado para cada linha com base em um conjunto relacionado de linhas. Essas funções possuem três elementos fundamentais: partição, ordenação e frame (Window Function Concepts and Syntax).
function over (
[partition by partition_expression]
[order by order_expression]
[frame]
)
-
Partição: a cláusula
partition bydivide as linhas em partições. Se omitida, o conjunto de resultados inteiro é tratado como uma única partição. -
Ordenação: a cláusula
order byordena as linhas dentro de cada partição.nullUsar a cláusula
order byem colunas com valores duplicados gera uma ordem de linhas não determinística. Para garantir uma ordenação consistente, especifique múltiplas colunas. Por exemplo:order by request_time, request_method. -
Frame: restringe as linhas dentro de uma partição. Não pode ser usado com funções de classificação. Sintaxe:
{ rows | range} { frame_start | frame_between }. Exemplo:range between unbounded preceding and unbounded following. Window Function Frame Specification.
Funções
|
Categoria |
Função |
Sintaxe |
Descrição |
SQL |
SPL |
|
Funções de agregação |
N/A |
Todas as funções de agregação podem ser usadas como funções de janela. |
√ |
× |
|
|
Funções de classificação |
|
Calcula a distribuição cumulativa de um valor dentro de uma partição, que corresponde à fração de linhas com valores menores ou iguais ao valor da linha atual. O valor retornado está no intervalo (0, 1]. |
√ |
× |
|
|
|
Calcula o rank de um valor em uma partição. Empates recebem o mesmo rank, e os ranks são consecutivos. Por exemplo, se duas linhas têm rank 1, o próximo rank é 2. |
√ |
× |
||
|
ntile(n) |
Divide as linhas ordenadas de uma partição em um número especificado de grupos, n. |
√ |
× |
||
|
|
Calcula o rank percentual de cada linha dentro de uma partição. |
√ |
× |
||
|
|
Calcula o rank de um valor em uma partição. Empates recebem o mesmo rank, e os ranks não são consecutivos. Por exemplo, se duas linhas têm rank 1, o próximo rank é 3. |
√ |
× |
||
|
|
Atribui um inteiro sequencial único a cada linha em uma partição, começando em 1. Por exemplo, três linhas com o mesmo valor recebem os ranks 1, 2 e 3. |
√ |
× |
||
|
Funções de deslocamento |
first_value(x) |
Retorna o valor de x da primeira linha de uma partição. |
√ |
× |
|
|
last_value(x) |
Retorna o valor de x da última linha de uma partição. |
√ |
× |
||
|
lag(x, offset, default_value) |
Retorna o valor da linha que está offset linhas acima da linha atual na partição de janela. Se a linha não existir, retorna default_value. |
√ |
× |
||
|
lead(x, offset, default_value) |
Retorna o valor da linha que está offset linhas abaixo da linha atual na partição de janela. Se a linha não existir, retorna default_value. |
√ |
× |
||
|
nth_value(x, offset) |
Retorna o valor da linha na posição offset dentro da partição de janela. |
√ |
× |
Funções de agregação
Todas as funções de agregação podem atuar como funções de janela. O exemplo a seguir usa sum().
Syntax
sum() over (
[partition by partition_expression]
[order by order_expression]
[frame]
)
Parameters
|
Parâmetro |
Descrição |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão de partição especificada. |
|
order by order_expression |
Ordena as linhas dentro de cada partição com base na expressão de ordenação especificada. |
|
frame |
Frame de janela, como |
Return value type
double
Examples
Calcula o salário de cada funcionário como proporção do total do respectivo departamento.
-
Instrução de consulta
* | SELECT department, staff_name, salary, round ( salary * 1.0 / sum(salary) over(partition by department), 3) AS salary_percentage -
Resultados da consulta: os resultados exibem dados de quatro funcionários no departamento
deve três no departamentoMarketing. A colunasalary_percentagemostra o salário de cada funcionário como fração do total do departamento.
Função cume_dist
Calcula a distribuição cumulativa de um valor dentro de uma partição: a razão entre o número de linhas com valores menores ou iguais ao da linha atual e o total de linhas. Retorna um valor no intervalo (0, 1].
Syntax
cume_dist() over (
[partition by partition_expression]
[order by order_expression]
)
Parameters
|
Parâmetro |
Descrição |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão de partição especificada. |
|
order by order_expression |
Ordena as linhas dentro de cada partição com base na expressão de ordenação especificada. |
Return value type
double
Examples
Calcula a distribuição cumulativa dos tamanhos de objetos no bucket OSS bucket00788.
-
Instrução de consulta
bucket=bucket00788 | select object, object_size, cume_dist() over ( partition by object order by object_size ) as cume_dist from oss-log-store
Função dense_rank
Retorna o rank de um valor dentro de uma partição. Empates recebem o mesmo rank, e os ranks são consecutivos, sem lacunas. Por exemplo, se duas linhas compartilham o rank 1, o próximo rank é 2.
Syntax
dense_rank() over (
[partition by partition_expression]
[order by order_expression]
)
Parameters
|
Parâmetro |
Descrição |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão de partição. |
|
order by order_expression |
Ordena as linhas dentro de cada partição com base na expressão de ordenação. |
Return value type
bigint
Examples
Calcula o rank salarial por departamento.
-
Instrução de consulta e análise
* | select department, staff_name, salary, dense_rank() over( partition by department order by salary desc ) as salary_rank order by department, salary_rank -
Resultados da consulta e análise: em Marketing, Blan Stark e Smith compartilham o rank 1 (salário 9000); Achilles ocupa o rank 2 (8000). Em dev, Rob é rank 1 (9000), Blan rank 2 (8500) e Sansa rank 3 (8000).
Função ntile
Divide as linhas ordenadas de uma partição em um número especificado de grupos.
Syntax
ntile(n) over (
[partition by partition_expression]
[order by order_expression]
)
Parameters
|
Parâmetro |
Descrição |
|
n |
O número de grupos em que as linhas serão divididas. |
|
partition by partition_expression |
Divide as linhas em partições usando a expressão de partição. |
|
order by order_expression |
Ordena as linhas dentro de cada partição pela expressão de ordenação. |
Return value type
bigint
Examples
Divide os dados de um objeto específico em três grupos.
-
Instrução de consulta
object=245-da918c.model | select object, object_size, ntile(3) over ( partition by object order by object_size ) as ntile from oss-log-store -
Resultados da consulta e análise: a consulta retorna nove linhas. Os valores de
object_size, em ordem crescente, são 3396, 3701, 3750, 3757, 3914, 3918, 7440, 7490 e 7521. Os valores correspondentes na colunantilesão 1, 1, 1, 2, 2, 2, 3, 3 e 3. Dessa forma,ntile(3)divide as nove linhas em três grupos iguais de três.
Função percent_rank
Calcula o rank percentual de cada linha em uma partição. Fórmula: (rank - 1) / (total_rows - 1), onde rank é o rank da linha atual e total_rows é o tamanho da partição.
Syntax
percent_rank() over (
[partition by partition_expression]
[order by order_expression]
)
Parameters
|
Parâmetro |
Descrição |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão fornecida. |
|
order by order_expression |
Ordena as linhas dentro de cada partição pela expressão fornecida. |
Return value type
double
Examples
Calcula o rank percentual de um objeto OSS por tamanho.
-
Instrução de consulta
object=245-da918c3e2dd9dc9cb4d9283b%2F555e2441b6a4c7f094099a6dba8e7a5f.model| select object, object_size, percent_rank() over ( partition by object order by object_size ) as ntile FROM oss-log-store -
Resultados da consulta e análise: seis linhas ordenadas por
object_size. A colunantileexibe valores de rank percentual distribuídos uniformemente de 0,0 a 1,0.
Função rank
Retorna o rank de cada linha dentro de uma partição. Empates recebem o mesmo rank, gerando lacunas na sequência. Por exemplo, se duas linhas compartilham o rank 1, o próximo rank é 3.
Syntax
rank() over (
[partition by partition_expression]
[order by order_expression]
)
Parameters
|
Parâmetro |
Descrição |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão de partição especificada. |
|
order by order_expression |
Ordena as linhas dentro de cada partição com base na expressão de ordenação especificada. |
Return value type
bigint
Examples
Classifica os funcionários por salário dentro de cada departamento.
-
Instrução de consulta e análise
* | select department, staff_name, salary, rank() over( partition by department order by salary desc ) as salary_rank order by department, salary_rank -
Resultados da consulta e análise: em Marketing, dois funcionários compartilham o rank 1 (salário 9000). O próximo rank é 3, demonstrando como empates criam lacunas na sequência.
Função row_number
Atribui um inteiro sequencial único a cada linha dentro de uma partição, começando em 1.
Syntax
row_number() over (
[partition by partition_expression]
[order by order_expression]
)
Parameters
|
Parâmetro |
Descrição |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão de partição especificada. |
|
order by order_expression |
Ordena as linhas dentro de cada partição com base na expressão de ordenação especificada. |
Return value type
bigint.
Examples
Classifica os funcionários por salário dentro de cada departamento.
-
Consulta
* | select department, staff_name, salary, row_number() over( partition by department order by salary desc ) as salary_rank order by department, salary_rank -
Seis linhas: em Marketing, Blan Stark (9000) é a linha 1, Smith (9000) a linha 2 e Achilles (8000) a linha 3. Em dev, Rob (9000) é a linha 1, Blan (8500) a linha 2 e Sansa (8000) a linha 3.
Função first_value
Retorna o valor da primeira linha de cada partição.
Syntax
first_value(x) over (
[partition by partition_expression]
[order by order_expression]
[frame]
)
Parameters
|
Parâmetro |
Descrição |
|
x |
O nome da coluna. Aceita qualquer tipo de dado. |
|
partition by partition_expression |
Divide as linhas em partições de janela com base na expressão de partição. |
|
order by order_expression |
Ordena as linhas dentro de cada partição de janela com base na expressão de ordenação. |
|
frame |
Especifica o frame de janela, um subconjunto da partição de janela atual. Por exemplo, |
Return value type
Retorna o mesmo tipo de dado que x.
Examples
Retorna o menor tamanho de cada objeto em um bucket OSS.
-
Instrução de consulta e análise
bucket :bucket90 | select object, object_size, first_value(object_size) over ( partition by object order by object_size range between unbounded preceding and unbounded following ) as first_value from oss-log-store -
Resultados da consulta e análise: sete linhas divididas em três grupos por object. Dentro de cada grupo, first_value corresponde ao menor object_size (a primeira linha em ordem crescente).
Função last_value
Retorna o valor da última linha de uma partição.
Syntax
last_value(x) over (
[partition by partition_expression]
[order by order_expression]
[frame]
)
Parameters
|
Parâmetro |
Descrição |
|
x |
O nome da coluna. Aceita qualquer tipo de dado. |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão de partição especificada. |
|
order by order_expression |
Ordena as linhas dentro de cada partição com base na expressão de ordenação especificada. |
|
frame |
Especifica o frame de janela, um subconjunto da partição atual. Por exemplo, |
Return value type
Mesmo tipo que x.
Examples
Encontra o maior tamanho de objeto no bucket OSS especificado.
-
Instrução de consulta e análise
bucket :bucket90 | select object, object_size, last_value(object_size) over ( partition by object order by object_size range between unbounded preceding and unbounded following ) as last_value from oss-log-store -
A consulta retorna três colunas: object, object_size e last_value. Para
245-da918c.model, sete linhas exibemobject_sizede 2383 a 6936, comlast_valueigual a 6936 em todas as linhas. Paradashboard%2F2020%2F05%2F20%2F16%2F47.csv, duas linhas têmobject_size2435 e 2603, comlast_valueigual a 2603.
Função lag
Retorna o valor da linha que está a um offset especificado antes da linha atual em uma partição.
Syntax
lag(x, offset, default_value) over (
[partition by partition_expression]
[order by order_expression]
[frame]
)
Parameters
|
Parâmetro |
Descrição |
|
x |
Uma coluna ou expressão de qualquer tipo de dado. |
|
offset |
O deslocamento, que especifica o número de linhas anteriores à linha atual. Se offset for 0, a função retorna o valor da linha atual. |
|
default_value |
Retorna default_value caso a linha no offset especificado não exista. |
|
partition by partition_expression |
Divide as linhas em partições de janela com base na expressão de partição especificada. |
|
order by order_expression |
Ordena as linhas dentro de cada partição de janela com base na expressão de ordenação especificada. |
|
frame |
Especifica o frame de janela, um subconjunto da partição de janela atual. Por exemplo, |
Return value type
Mesmo tipo que x.
Examples
Calcula os UVs diários e a taxa de crescimento dia a dia.
-
Instrução de consulta
* | select day, UV, UV * 1.0 /(lag(UV, 1, 0) over()) as diff_percentage from ( select approx_distinct(client_ip) as UV, date_trunc('day', __time__) as day from log group by day order by day asc ) -
Resultados da consulta e análise: oito registros de 2 a 9 de agosto de 2021. O diff_percentage da primeira linha é Infinity porque
lagretorna o valor padrão 0, causando uma divisão por zero. As linhas seguintes exibem a razão entre os UVs do dia atual e do dia anterior, como 2,098 e 0,976.
Função lead
Retorna o valor da linha que está a um offset especificado após a linha atual em uma partição.
Syntax
lead(x, offset, default_value) over (
[partition by partition_expression]
[order by order_expression]
[frame]
)
Parameters
|
Parâmetro |
Descrição |
|
x |
Uma coluna ou expressão de qualquer tipo de dado. |
|
offset |
O número de linhas após a linha atual. Se offset for 0, a função retorna o valor da linha atual. |
|
default_value |
Caso a linha no offset especificado não exista, retorna default_value. |
|
partition by partition_expression |
Divide as linhas em partições de janela com base na expressão de partição especificada. |
|
order by order_expression |
Ordena as linhas dentro de cada partição de janela com base na expressão de ordenação especificada. |
|
frame |
Especifica o frame de janela, por exemplo, |
Return value type
Retorna um valor do mesmo tipo de dado que x.
Examples
Calcula a proporção de UVs por hora em 26 de agosto de 2021.
-
Instrução de consulta
* | select time, UV, UV * 1.0 /(lead(UV, 1, 0) over()) as diff_percentage from ( select approx_distinct(client_ip) as uv, date_trunc('hour', __time__) as time from log group by time order by time asc ) -
Resultados da consulta e análise: a consulta retorna oito linhas com os visitantes únicos por hora (
UV) e a razão entre os UVs da hora atual e da hora seguinte (diff_percentage), das 00:00 às 07:00 do dia 26 de agosto de 2021.
Função nth_value
Retorna o valor da offset-ésima linha de uma partição.
Syntax
nth_value(x, offset) over (
[partition by partition_expression]
[order by order_expression]
[frame]
)
Parameters
|
Parâmetro |
Descrição |
|
x |
Uma coluna ou expressão. Aceita qualquer tipo de dado. |
|
offset |
O deslocamento da linha. Deve ser um inteiro positivo. |
|
partition by partition_expression |
Divide as linhas em partições com base na expressão de partição. |
|
order by order_expression |
Ordena as linhas dentro de cada partição com base na expressão de ordenação. |
|
frame |
Especifica o frame de janela, um subconjunto da partição atual. Por exemplo, |
Return value type
Mesmo tipo de dado que x.
Examples
Retorna o funcionário com o segundo maior salário por departamento.
-
Instrução de consulta
* | select department, staff_name, salary, nth_value(staff_name, 2) over( partition by department order by salary desc range between unbounded preceding and unbounded following ) as second_highest_salary from log -
Resultados da consulta: a coluna second_highest_salary exibe Blan (8500) para dev e San (7000) para Marketing em todas as linhas de cada partição.