20th Jul 2022 6 minutos de leitura Funções da Janela SQL vs. GROUP BY: Qual é a diferença? Ignacio L. Bisso sql aprender sql window functions Índice Revisão rápida de GROUP BY GROUP BY vs Funções de Janela (Window Functions) em SQL O Poder de Funções de Janela (Window Functions) em SQL Funções de Janela (Window Functions) em SQL vs Funções Agregadas Fechando a Janela Um equívoco muito comum entre os usuários de SQL é que não há muita diferença entre funções de janela SQL e funções agregadas ou a cláusula GROUP BY. Entretanto, as diferenças são muito significativas. Talvez o único ponto semelhante entre GROUP BY e funções de janela é que ambas permitem executar uma função (como AVG, MAX, MIN, ou COUNT) em um grupo de registros. Eu diria que o poder especial das funções de janela é que elas nos permitem obter resultados que de outra forma seriam quase impossíveis de se obter. Neste artigo, vamos rever o uso de funções de janela vs GROUP BY e funções de janela vs funções agregadas. Revisão rápida de GROUP BY A cláusula GROUP BY nos permite agrupar um conjunto de registros com base em alguns critérios e aplicar uma função (por exemplo, AVG ou MAX) a cada grupo, obtendo um resultado para cada grupo de registros. Vamos ver um exemplo. Temos uma tabela chamada employee com um total de cinco funcionários e três departamentos: Employee_NameDepartmentSalary John RobertsFinance2300 Peter HudsonMarketing1800 Sue GibsonFinance2000 Melinda BishopMarketing1500 Nancy HudsonIT1950 fig1: a tabela de funcionários Suponhamos que queremos obter o salário médio por departamento e o salário máximo para cada departamento. Devemos utilizar a seguinte consulta: SELECT Department, avg(salary) as average, max(salary) as top_salary FROM employee GROUP BY department A imagem abaixo mostra o resultado: Departmentaveragetop_salary Marketing16501800 Finance21502300 IT19501950 GROUP BY vs Funções de Janela (Window Functions) em SQL Ao comparar as funções de janela e GROUP BY, é essencial lembrar que GROUP BY colapsa os registros individuais em grupos; após usar GROUP BY, você não pode se referir a nenhum campo individual porque ele está colapsado. Mais tarde, falaremos em profundidade sobre este tópico. Por enquanto, mencionaremos apenas que as funções de janela não colapsam os registros individuais. Portanto, se você quiser criar um relatório com o nome de um funcionário, salário e o salário máximo do departamento do funcionário, você não pode fazê-lo com GROUP BY. Os registros individuais de cada funcionário são colapsados pela cláusula GROUP BY department. Para este tipo de relatório, você precisa usar funções de janela, que é o tópico da próxima seção. Se você quiser aprofundar as nuances do SQL GROUP BY e relatórios, recomendamos nosso curso interativo Como Criar Relatórios Básicos em SQL. O Poder de Funções de Janela (Window Functions) em SQL As funções de janela são uma característica poderosa do SQL. Elas nos permitem aplicar funções como AVG, COUNT, MAX, e MIN em um grupo de registros, deixando os registros individuais acessíveis. Como os registros individuais não são colapsados, podemos criar consultas mostrando os dados do registro individual junto com o resultado da função janela. Isto é o que torna as funções de janela tão poderosas. Suponhamos que queremos obter uma lista de nomes de funcionários, salários e o salário mais alto em seus departamentos. SELECT employee_name, department, salary, max(salary) OVER (PARTITION BY department) as top_salary FROM employee A imagem seguinte mostra o resultado: Employee_NameDepartmentsalarytop_salary John RobertsFinance23002300 Peter HudsonMarketing18001800 Sue GibsonFinance20002300 Melinda BishopMarketing15001800 Nancy HudsonIT19501950 Na consulta anterior, utilizamos uma função de janela: max(salary) OVER (PARTITION BY department) as top_salary A função de janela é MAX() e nós a aplicamos ao conjunto de registros definidos pela cláusula OVER (PARTITION BY department)que são os registros com o mesmo valor no campo do departamento. Por fim, renomeamos a coluna top_salary. No resultado da consulta, temos filas para funcionários individuais. Se usássemos GROUP BY ao invés de funções de janela, teríamos linhas para cada departamento. As funções de janela têm uma sintaxe bastante verbosa; se você quiser entrar em detalhes, sugiro o curso "Funções de Janela (Window Functions) em SQL", que é um tutorial passo a passo que o leva através das funções de janela SQL usando exemplos e exercícios. Funções de Janela (Window Functions) em SQL vs Funções Agregadas Quando comparamos funções de janela e funções agregadas, notamos uma característica super poderosa no lado das funções de janela: funções posicionais. Elas nos permitem obter um valor de coluna de outros registros na mesma janela. Esta é uma capacidade realmente incrível, permitindo aos usuários SQL criar relatórios complexos em apenas algumas linhas. Vamos discutir brevemente duas destas funções: LEAD() e LAG(). A função LAG() retorna o valor da coluna do registro anterior na janela, enquanto LEAD() retorna o valor da coluna do próximo registro na janela. É muito importante ter a janela ordenada pela coluna da direita, se você quiser usar estas funções. Vamos ver um exemplo de como podemos usar estas funções. Suponha que tenhamos uma tabela que armazene as ações da empresa com seus valores de mercado em um determinado momento. A tabela pode ser parecida com esta: share_symboltimestampvalue OILBEST2020-03-05 10:00120 OILBEST2020-03-05 12:00123 OILBEST2020-03-05 15:00122 BANKWEB2020-03-05 10:0091 BANKWEB2020-03-05 12:0087 BANKWEB2020-03-05 15:0099 fig2: a tabela de ações Suponhamos que queremos um relatório mostrando o valor de cada ação com seu valor anterior e a porcentagem de variação relacionada ao valor anterior. Podemos fazê-lo usando a função LEAD() para obter o valor anterior da ação. Note que usamos ORDER BY timestamp ao definir a partição (ou seja, a janela de registros). Voltaremos a este ponto mais tarde. SELECT share_symbol, timestamp, value, LAG(value) OVER (PARTITION BY share_symbol ORDER BY timestamp ) AS previous_value, TRUNC(((value - (LAG(value) OVER (PARTITION BY share_symbol ORDER BY timestamp )))*100)/value,2) AS percentage_variation FROM share Note que as colunas previous_value e percentage_variation são colunas calculadas. Elas utilizam valores de diferentes registros na mesma tabela. share_symboltimestampvalueprevious_valuepercentage_variation OILBEST2020-03-05 10:00120 OILBEST2020-03-05 12:001231202.43 OILBEST2020-03-05 15:00122123-0.81 BANKWEB2020-03-05 10:0091 BANKWEB2020-03-05 12:008791-4.59 BANKWEB2020-03-05 15:00998712.12 Quando usamos funções posicionais, é muito importante colocar uma cláusula ORDER BY junto com a cláusula PARTITION (como fizemos na consulta anterior). Se não usarmos a ORDER BY correta, os resultados podem estar errados. Por quê? Porque as funções posicionais funcionam com base na ordem dos registros na janela. Vamos examinar isto um pouco mais. A função FIRST_VALUE() retorna um valor de coluna do primeiro registro na janela. LAG() Como sabemos, retorna o valor da coluna do registro anterior na janela. Ter a ordem correta da janela é crucial; imagine o que você obteria com estas funções de outra forma! Em nosso exemplo, queremos o valor de mercado cronológico anterior para uma ação específica. Assim, utilizamos ORDER BY timestamp. Se omitirmos o ORDER BY ou encomendarmos por outra coluna, o resultado seria errado. Em alguns casos específicos, as funções posicionais podem retornar valores errados por causa de uma janela parcialmente preenchida. E há mais funções de janela, como RANK(), NTH_VALUE() e LAST_VALUE(). Não temos espaço para cobrir tudo isso aqui, mas sugiro verificar este artigo explicando as funções de janela e estes exemplos de funções de janela para saber mais. Fechando a Janela Neste artigo, exploramos as diferenças entre as funções de janela e GROUP BY. Vimos exemplos com várias funções agregadas e de janela. Também falamos sobre uma importante limitação da cláusula GROUP BY, ou seja, o "colapso dos registros". Esta limitação não está presente nas funções de janela, permitindo aos desenvolvedores de SQL combinar dados de nível de registro com os resultados das funções de janela na mesma consulta. Outra vantagem das funções de janela é sua capacidade de combinar valores de consulta de diferentes registros (da mesma janela) na mesma linha do conjunto de resultados. Se você estiver interessado em aprender mais sobre funções de janela, sugiro o Funções de Janela (Window Functions) em SQL curso, onde você pode aprender as funções da janela SQL usando exercícios interativos e explicações detalhadas. Tags: sql aprender sql window functions