Voltar para a lista de artigos Artigos
15 minutos de leitura

Explicação das funções de janela do BigQuery

Manter-se atualizado com as tendências de análise de dados dá à sua organização - e ao seu currículo - a vanguarda. Neste artigo, daremos uma olhada nas funções de janela do BigQuery e como você pode usá-las para obter insights mais profundos sobre seus dados.

O BigQuery do Google, lançado em 2010, está ganhando força como uma opção popular entre as organizações que precisam analisar rapidamente grandes quantidades de informações e comparar seus próprios dados com dados estatísticos de domínio público.

Desde que o Google alinhou a linguagem de recuperação de dados do BigQuery para ficar em conformidade com o SQL padrão - e incluiu recursos avançados, como funções de janela SQL -, sua popularidade aumentou. Muitas organizações agora incluem as habilidades em BigQuery como um requisito obrigatório, e isso significa que as habilidades em SQL estão mais em demanda do que nunca. Este artigo explica por que o conhecimento de SQL é essencial para trabalhar com o BigQuery

O SQL continua ocupando seu lugar como a principal habilidade para quem precisa trabalhar com dados. Se você ainda não é um guru do SQL, talvez se interesse pela nossa trilha de aprendizadoSQL de A a Z . Ela inclui 7 cursos que o levam do iniciante absoluto ao especialista em SQL. O curso tem centenas de desafios de codificação do mundo real e leva cerca de 84 horas para ser concluído. Como você pode acessar os bancos de dados de amostra pelo navegador, não é necessário instalar nenhum software para começar.

O que é o BigQuery?

O Google BigQuery é um data warehouse de alta velocidade localizado na nuvem. Projetado especialmente para armazenar dados usados para análise, ele pode processar petabytes de dados em minutos. Se você ainda não entendeu o que são petabytes, um petabyte é um quatrilhão de bytes (ou um milhão de gigabytes).

Você paga pelo que usa no BigQuery, portanto, o custo de armazenar e analisar grandes quantidades de dados geralmente é muito menor do que investir em muitos discos rígidos. E como todos os tipos de dados estatísticos úteis de governos e organizações mundiais são armazenados publicamente no BigQuery, você pode acessá-los para obter insights sobre como o desempenho da sua organização pode ser aprimorado.

O que é SQL Funções de Janela (Window Functions) em SQL?

As funções de janela também são conhecidas como funções analíticas ou funções OVER. Elas foram adicionadas ao padrão SQL em 2003, e a maioria dos principais fornecedores de bancos de dados começou a implementá-las a partir de 2010. Portanto, são uma adição relativamente nova ao SQL.

Antes de as funções de janela serem incluídas no SQL, você podia listar linhas individuais ou calcular agregados, como totais e médias. Não era possível fazer as duas coisas com facilidade na mesma consulta, a menos que você escrevesse subconsultas complexas - e provavelmente lentas e ineficientes.

Isso significa que você poderia ter uma lista como esta ...

Student IDSubjectScore
1Math63
1Science50
2Math59

... ou você poderia mostrar agregados como este:

SubjectClass Average
Math52
Science61
English55
Overall Average56

Nesse exemplo, se você quisesse saber como a pontuação de um aluno individual se comparava à média da turma, teria que examinar os dois relatórios lado a lado. Seria muito melhor se você pudesse ver a média da turma na mesma linha que a pontuação de um aluno, assim:

Student IDSubjectScoreClass Average
1Math6362
1Science5061
2Math5952

Como mencionei, você poderia fazer isso usando subconsultas. Mas as subconsultas são notoriamente lentas para serem executadas e podem tornar sua consulta muito complicada.

Esse é o tipo de coisa que as funções de janela permitem que você faça com facilidade e eficiência: incluir agregados juntamente com detalhes na mesma linha.

Por que elas são chamadas de Funções de Janela (Window Functions) em SQL?

Elas são chamadas de funções de janela porque, ao examinar uma linha individual, você também pode "olhar pela janela" e extrair informações de todo o conjunto de dados ou das linhas relacionadas à linha atual.

Como exemplo, vamos examinar uma tabela de notas dos alunos:

Student IDTeacher IDSubjectGrade
11Math63
21Math80
32Math60
42Math45
51Math52
61Math70
72Math65
12Science70
22Science62
32Science90
42Science30
52Science53
15English59
35English70
55English45
65English62
112History55
312History67
412History58

Conforme o exemplo anterior, queremos mostrar a média da turma ao lado de cada aluno, de modo que uma única linha tenha a seguinte aparência:

Student IDSubjectGradeClass Average
4Math4562

Para isso, precisamos examinar a média de todos os outros alunos quando estivermos extraindo essa linha e mostrar o resultado junto com os outros dados.

BigQuery Funções de Janela (Window Functions) em SQL Explained

No SQL, as funções de janela usam uma janela deslizante de linhas para extrair informações adicionais de todo o conjunto de dados ou de um subconjunto relacionado à linha atual.

No diagrama acima, a linha atual é um resultado de matemática e a janela inclui todas as notas de matemática.

Quando estivermos extraindo essa linha ...

Student IDSubjectGradeClass Average
1Science7062

... precisaremos que a janela "deslize" para que possamos visualizar todos os resultados de ciências a fim de calcular a média de ciências.

As funções de janela têm muitos dos mesmos recursos que a cláusula GROUP BY, mas a diferença é que elas nos permitem visualizar agregados e detalhes lado a lado.

Sintaxe do BigQuery Funções de Janela (Window Functions) em SQL

A cláusula OVER()

A cláusula OVER() indica que você está usando uma função de janela. Você escreveria sua consulta como de costume e incluiria os agregados desejados junto com os nomes das outras colunas. Cada agregado é identificado com a cláusula OVER(). Quando você usa essa cláusula isoladamente, a "janela" é o conjunto de dados inteiro. Falarei sobre janelas deslizantes um pouco mais adiante neste artigo.

Por exemplo, se você quisesse extrair todos os resultados de matemática e mostrar a média da turma e a nota mais alta e mais baixa em relação à nota de cada aluno, sua consulta seria semelhante a esta:

SELECT 
  student_id,
  grade,
  AVG(grade) OVER() AS average,
  MIN(grade) OVER() AS lowest,
  MAX(grade) OVER() AS highest
FROM exam_results
WHERE subject = 'Math';

Seus resultados teriam a seguinte aparência:

student_idgradeaveragelowesthighest
163624580
280624580
360624580
445624580
552624580
670624580
765624580

A cláusula PARTITION BY

Essa cláusula usa uma janela deslizante. Em vez de uma janela que contém todo o conjunto de dados, ela inclui apenas uma partição (ou parte) do conjunto.

No exemplo anterior, incluí somente os resultados matemáticos, excluindo todos os outros usando a cláusula WHERE. Se você quisesse um relatório que mostrasse os resultados de todas as disciplinas, mas calculasse a média usando somente as linhas em que a disciplina correspondesse à linha atual, você usaria a cláusula PARTITION BY:

SELECT 
  student_id,
  subject,
  grade,
  AVG(grade) OVER(PARTITION BY subject) AS average
FROM exam_results;

Dê uma olhada nesta cópia com código de cores da tabela de notas dos alunos para ver como as partições funcionarão:

Student IDTeacher IDSubjectGrade
11Math63
21Math80
32Math60
42Math45
51Math52
61Math70
72Math65
12Science70
22Science62
32Science90
42Science30
52Science53
15English59
35English70
55English45
65English62
112History55
312History67
412History58

Ao processar cada linha, as linhas incluídas na janela mudam com base no valor da coluna subject. Isso significa que a média é calculada somente para a partição do conjunto de dados em que o assunto corresponde à linha atual. Você pode visualizá-la da seguinte forma:

BigQuery Funções de Janela (Window Functions) em SQL Explained

Os resultados seriam os seguintes:

Student IDSubjectGradeClass Average
1Math6362
2Math8062
3Math6062
4Math4562
5Math5262
6Math7062
7Math6562
1Science7061
2Science6261
3Science9061
4Science3061
5Science5361
1English5959
3English7059
5English4559
6English6259
1History5560
3History6760
4History5860

A cláusula ORDER BY

A cláusula ORDER BY dentro da função OVER() usa um tipo diferente de janela deslizante. Quando você usa OVER(ORDER BY column_name), a janela inclui somente as linhas em que o valor da coluna especificada é menor ou igual ao valor da coluna na linha atual.

A cláusula ORDER BY é útil para calcular totais em execução e médias móveis. Como exemplo, usarei uma tabela chamada monthly_transactions que contém transações de contas bancárias:

account_idtran_datetransactionvalue
12023-09-01Opening Balance500.00
12023-09-03Deposit137.45
12023-09-12Withdrawal-200.00
12023-09-18Withdrawal-250.00
22023-09-01Opening Balance1200.00
22023-09-14Deposit900.00
22023-09-20Purchase-318.90

A consulta abaixo listará as transações da ID de conta 1, mostrando um saldo em andamento.

SELECT 
  account_id,
  tran_date,
  transaction,
  value,
  SUM(value) OVER(ORDER BY tran_date) AS balance
FROM monthly_transactions
WHERE account_id = 1;

A inclusão da cláusula ORDER BY dentro da cláusula OVER controla uma janela deslizante.

Se desejar, você também pode usar a cláusula ORDER BY usual no final da consulta para controlar a ordem final das linhas no relatório. Elas não precisam ser mostradas na ordem original.

Por padrão, o uso de ORDER BY dentro da cláusula OVER faz com que a janela deslize de modo a exibir apenas as linhas em que a data é menor ou igual à data da linha atual. Há outras palavras-chave que podem alterar esse padrão, mas elas estão um pouco além do escopo deste artigo.

Você pode visualizar dessa forma:

BigQuery Funções de Janela (Window Functions) em SQL Explained

Os resultados seriam os seguintes:

account_idtran_datetransactionvaluebalance
12023-09-01Opening Balance500.00500.00
12023-09-03Deposit137.45637.45
12023-09-12Withdrawal-200.00437.45
12023-09-18Withdrawal-250.00187.45
22023-09-01Opening Balance1200.001200.00
22023-09-14Deposit900.002100.00
22023-09-20Purchase-318.901781.10

Uso de ORDER BY com a cláusula PARTITION BY

Se quiser mostrar todas as contas com seus saldos correntes, você pode usar PARTITION BY e ORDER BY juntos:

SELECT 
  account_id,
  tran_date,
  transaction,
  value,
  SUM(value) OVER(PARTITION BY account_id ORDER BY tran_date) AS balance
FROM monthly_transactions
ORDER BY account_id, tran_date

A cláusula PARTITION BY fará com que a janela deslizante inclua somente as linhas em que account_id corresponda à linha atual. A cláusula ORDER BY fará com que a janela deslizante inclua somente linhas dentro dessa partição em que a data seja menor ou igual à data da linha atual.

Os resultados seriam os seguintes:

account_idtran_datetransactionvaluebalance
12023-09-01Opening Balance500.00500.00
12023-09-03Deposit137.45637.45
12023-09-12Withdrawal-200.00437.45
12023-09-18Withdrawal-250.00187.45
22023-09-01Opening Balance1200.001200.00
22023-09-14Deposit900.002100.00
22023-09-20Purchase-318.901781.10

Cada conta tem seu próprio saldo corrente separado.

SQL Funções de Janela (Window Functions) em SQL disponível no BigQuery

Você viu como as funções agregadas comuns do SQL, como SUM(), AVG(), MIN() e MAX() podem ser usadas em conjunto com a cláusula OVER para extrair agregados de uma janela de dados.

O Google BigQuery, assim como muitos outros dialetos SQL, tem funções adicionais que podem fornecer insights mais profundos sobre os dados. Aqui estão alguns exemplos.

RANK()

Essa função classifica o conjunto de dados do mais alto para o mais baixo em uma coluna especificada. Ela pode responder a perguntas como:

  • Qual foi a posição de cada aluno na classe, com base nos resultados dos exames?
  • Quais produtos foram mais lucrativos?
  • Quais clientes gastaram mais dinheiro?
  • Qual depósito recebeu o maior número de reclamações?

Usando a tabela de amostra que vimos anteriormente, vamos classificar os alunos por resultados de exames usando essa consulta:

SELECT 
  student_id,
  subject,
  grade,
  RANK() OVER(PARTITION BY subject ORDER BY grade desc) AS place
FROM exam_results
ORDER BY subject, grade DESC;

O resultado seria:

student_idsubjectgradeplace
3English701
6English622
1English593
5English454
3History671
4History582
1History553
2Math801
6Math702
7Math653
1Math634
3Math605
5Math526
4Math457
3Science901
1Science702
2Science623
5Science534
4Science305

Ao calcular esses resultados, a cláusula PARTITION BY subject faz com que o SQL examine apenas os resultados da mesma matéria da linha atual. A cláusula ORDER BY grade DESC os classifica em ordem decrescente de nota. A função RANK() classifica os alunos nessa ordem.

Como o aluno 3 tem a nota mais alta em inglês, sua classificação é 1; o aluno 6, o próximo mais alto, tem a classificação 2 nessa matéria. O aluno 2 tem a nota mais alta em matemática e é classificado como 1.

DENSE_RANK()

DENSE_RANK() é usado com a mesma finalidade que RANK. A diferença entre eles pode ser melhor explicada observando-se esses resultados de consulta, que representam pontuações em uma competição de tiro.

Usando RANK, a consulta seria:

SELECT 
  competitor_no,
  score,
  RANK() OVER(ORDER BY score desc) AS rank
FROM match_results
ORDER BY score DESC;

Os resultados são:

Competitor NoScoreRank
4851
5832
10832
9814
2765
6765
7727
3708
8689
16210

Os concorrentes 5 e 10 empataram em segundo lugar e ambos receberam a classificação 2. O concorrente 9 é o próximo mais alto e recebeu a classificação 4. O terceiro lugar não foi incluído.

Usando DENSE_RANK, a consulta é:

SELECT 
  competitor_no,
  score,
  DENSE RANK() OVER(ORDER BY score desc) AS rank
FROM match_results
ORDER BY score DESC;

Os resultados são:

Competitor NoScoreRank
4851
5832
10832
9813
2764
6764
7725
3706
8687
1628

Os concorrentes 5 e 10 ainda estão classificados como 2, mas o terceiro lugar não foi excluído: O concorrente 9 agora tem uma classificação de 3.

Ambas as funções têm a mesma sintaxe. Se quiséssemos recodificar a consulta de notas dos alunos anteriores usando a função DENSE_RANK(), ela teria a seguinte aparência:

SELECT 
  student_id,
  subject,
  grade,
  DENSE_RANK() OVER(PARTITION BY subject ORDER BY grade desc) AS class_place
FROM exam_results
ORDER BY subject, grade DESC

Mas como não há valores empatados, o resultado seria o mesmo.

ROW_NUMBER()

A função ROW_NUMBER() funciona de forma semelhante às duas funções anteriores, mas as linhas são simplesmente numeradas em ordem. Se as linhas tiverem o mesmo valor, elas serão numeradas consecutivamente, dependendo de qual foi encontrada primeiro. Aqui estão os resultados da consulta da competição de tiro usando ROW_NUMBER() em vez de RANK() ou DENSE_RANK():

Competitor NoScoreRank
4851
5832
10833
9814
2765
6766
7727
3708
8689
16210

LAG()

Essa função permite que você compare os dados da linha anterior do conjunto de resultados com os dados da linha atual. É ideal para comparações ano a ano, permitindo que você descubra tendências e identifique problemas de desempenho comercial.

LAG() e a função relacionada LEAD() só pode ser usada em conjunto com a cláusula OVER(ORDER BY).

Como exemplo, veja a tabela a seguir, que contém dados de vendas de uma pequena empresa:

yearsales_valuesales_quantityprofit
2019540009008000
202075000120011000
2021300004501000
202260000100007000

A consulta de amostra para comparar os números ano a ano é:

SELECT 
  year,
  sales_value,
  sales_quantity,
  profit,
  LAG(sales_value) OVER(ORDER BY year) as ly_value,
  LAG(sales_quantity) OVER(ORDER BY year) as ly_qty,
  LAG(profit) OVER(ORDER BY year) as ly_profit,
  profit - LAG(profit) OVER(ORDER BY year) as inc_dec
FROM annual_sales
ORDER BY year;

Os resultados dessa consulta são:

yearsales_valuesales_quantityprofitly_valuely_qtyly_profitinc_dec
2019540009008000NULLNULLNULLNULL
2020750001200110005400090080003000
202130000450100075000120011000-10000
2022600001000070003000045010006000

Vamos dar uma olhada nessa linha da consulta e ver o que ela realmente fez:

LAG(sales_value) OVER(ORDER BY year) as ly_value

Nessa linha do resultado ...

yearsales_valuesales_quantityprofitly_valuely_qtyly_profitinc_dec
2020750001200110005400090080003000

... nossa linha atual é para o ano de 2020. A função LAG() em conjunto com ORDER BY year faz com que o SQL examine a linha do ano anterior (2019) e extraia o valor de vendas dela sob o título ly_value.

Você notará que, na primeira linha, as colunas calculadas pela função LAG() contêm um valor nulo, pois não há registro anterior.

LEAD()

A função LEAD() é o inverso de LAG(): ela obtém dados da linha após a linha atual, em vez da anterior.

Para comparar o lucro entre o ano atual, o ano anterior e o ano seguinte usando a mesma tabela de amostra, a consulta seria

SELECT 
  year,
  profit,
  LAG(profit) OVER(ORDER BY year) as ly_profit,
  profit - LAG(profit) OVER(ORDER BY year) as ly_inc_dec,
  LEAD(profit) OVER(ORDER BY year) as ny_profit,
  LEAD(profit) OVER(ORDER BY year) - profit as ny_inc_dec
FROM annual_sales
ORDER BY year;

Os resultados dessa consulta seriam:

yearprofitly_profitly_inc_decny_profitny_inc_dec
20198000NULLNULL110003000
202011000800030001000-10000
2021100011000-1000070006000
2022700010006000NULLNULL

As colunas ny_profit e ny_inc_dec usam a função LEAD(), que faz com que o SQL examine a próxima linha em sequência para extrair esses campos. Quando a linha atual for de 2019, esses dois campos serão extraídos da linha de 2020.

Isso deve ter lhe dado uma ideia de algumas das funções de janela SQL úteis disponíveis no BigQuery. Você encontrará uma lista completa de funções na documentação SQL do BigQuery.

Para obter mais exemplos de funções de janela, consulte o artigo Exemplos de funções de janela SQL. Você também pode encontrar um guia de referência rápida para a sintaxe das funções de janela SQL em nosso Funções de Janela (Window Functions) em SQL Cheat Sheet.

Usos práticos do BigQuery Funções de Janela (Window Functions) em SQL

No mundo real, há muitas maneiras pelas quais as funções de janela do BigQuery podem lhe fornecer insights para ajudar sua organização a ter um desempenho melhor. Elas são muito poderosas e permitem que você produza relatórios complexos com muita rapidez.

Aqui estão algumas ideias de como as funções de janela do BigQuery podem ser usadas:

Próximas etapas com o BigQuery Funções de Janela (Window Functions) em SQL

Agora que você já viu o que as funções de janela do SQL podem fazer no BigQuery e em outros sistemas de gerenciamento de banco de dados, é hora de pensar em aprimorar suas habilidades nessa importante área.

Um bom lugar para começar é o curso SQL Funções de Janela (Window Functions) em SQL do site LearnSQL.com.br. Você aprenderá passo a passo como usar as técnicas que viu neste artigo, com uma explicação completa de cada tópico. Você também terá muita prática, com mais de 200 exercícios interativos para garantir que saiba como extrair informações complexas em situações do mundo real. A ajuda está disponível em caso de dúvidas, e você poderá acessar bancos de dados de amostra por meio do navegador. O curso leva cerca de 20 horas para ser concluído.

Se você realmente quiser se tornar um especialista, poderá praticar mais a solução de problemas complexos trabalhando no nosso Funções de Janela (Window Functions) em SQL Practice Set. Você terá 100 exemplos de relatórios complexos usando três bancos de dados diferentes.

Você também pode ler este artigo sobre como praticar funções de janela, e pode saber mais sobre a sintaxe do BigQuery aqui.

Se estiver procurando um emprego de alto nível em análise de dados ou ciência de dados, é muito provável que você seja solicitado a demonstrar seu conhecimento de funções de janela SQL na entrevista. Para ter uma ideia do tipo de perguntas que podem ser feitas a você (e como respondê-las), aqui está um artigo que discute as principais perguntas da entrevista sobre funções de janela SQL.

Dê os primeiros passos hoje para levar suas habilidades de análise de dados para o próximo nível!