21st Jul 2022 9 minutos de leitura Como definir uma moldura de janela em funções de janela SQL Ignacio L. Bisso sql aprender sql window functions Índice Usando PARTITION BY para definir uma moldura de janela Ordenando as linhas dentro de uma moldura de janela com ORDENAMENTO POR Definindo os limites da moldura de janela com ROWS Definindo Limites de Janela com RANGE Aproveite a vantagem de Funções de Janela (Window Functions) em SQL! A função de janela é um recurso super poderoso da linguagem SQL. No núcleo de qualquer função de janela, há um conjunto de registros, chamado de quadro de janela, definido usando um Cláusula OVER. Saber que registros estão na moldura da janela, como eles são ordenados e quais são seus limites superior e inferior, é fundamental para entender como funciona a janela. Neste artigo, analisaremos e explicaremos com exemplos como você pode definir diferentes tipos de esquadrias de janela. Continue lendo para dar um passo importante no crescimento de suas habilidades SQL! Usando PARTITION BY para definir uma moldura de janela As funções da janela SQL realizam cálculos com base em um conjunto de registros. Por exemplo, você pode querer calcular o salário médio de um grupo específico de registros de funcionários. Este grupo de registros é chamado de quadro de janela, e sua definição é central para entender como funcionam as funções de janela e como podemos tirar proveito delas. O quadro de janela é um conjunto de linhas relacionadas com a linha atual onde a função de janela é usada para o cálculo. O quadro de janela pode ser um conjunto diferente de linhas para a próxima linha no resultado da consulta, uma vez que depende da linha atual sendo processada. Cada linha no conjunto de resultados da consulta tem sua própria moldura de janela. No restante deste artigo, mostraremos exemplos de consultas com base em um banco de dados de um grupo de concessionárias de automóveis. O grupo armazena as informações de vendas agrupadas por mês em uma tabela chamada monthly_car_sales. Abaixo está a tabela com alguns dados de exemplo: monthly_car_sales yearmonthmakemodeltypequantityrevenue 202101FordF100PickUp402500000 202101FordMustangCar91010000 202101RenaultFuegoCar209000000 202102RenaultFuegoCar5023000000 202102FordF100PickUp201200000 202102FordMustangCar101050000 202103RenaultMeganeCar5020000000 202103RenaultKoleosCar151004000 202103FordMustangCar202080000 202104RenaultMeganeCar5020000000 202104RenaultKoleosCar151004000 202104FordMustangCar252520000 Uma maneira simples de criar uma estrutura de janela é usando uma cláusula OVER com uma subcláusula PARTITION BY. No seguinte exemplo SQL, geramos um relatório de receita por marca do carro para o ano 2021. SELECT make, SUM(revenue) OVER (PARTITION BY make) AS total_revenue FROM monthly_car_sales WHERE year = 2021 Abaixo, as esquadrias geradas pela consulta anterior são mostradas em cores diferentes (vermelho para Ford e azul para Renault). Todos os registros com o mesmo valor na coluna make (as linhas com o código de cores abaixo) pertencem à mesma armação de janela. Como temos apenas dois valores diferentes na coluna make, temos duas armações de janela. yearmonthmakemodeltypequantityrevenue 202101FordF100PickUp402500000 202101FordMustangCar91010000 202101RenaultFuegoCar209000000 202102RenaultFuegoCar5023000000 202102FordF100PickUp201200000 202102FordMustangCar101050000 202103RenaultMeganeCar5020000000 202103RenaultKoleosCar151004000 202103FordMustangCar202080000 202104RenaultMeganeCar4015000000 202104RenaultKoleosCar201504000 202104FordMustangCar252520000 O resultado da consulta é: maketotal_revenue Ford10360000 Renault69508000 Gostaria de sugerir 2 artigos onde você pode encontrar muitas informações introdutórias sobre as funções da janela SQL: "SQL Course of The Month - Funções de Janela (Window Functions) em SQL " e "When Do I Use SQL Funções de Janela (Window Functions) em SQL?". Ordenando as linhas dentro de uma moldura de janela com ORDENAMENTO POR Além de PARTITION BY, podemos usar uma subcláusula ORDER BY para encomendar as filas dentro de uma armação de janela. Ter a estrutura da janela ordenada por alguns critérios nos permite utilizar funções de janela analíticas como LEAD(), LAG(), e FIRST_VALUE(), entre outras. Por exemplo, se quisermos obter a diferença de receita entre meses consecutivos, podemos encomendar a armação de janela por mês. Então, dada qualquer linha atual, a função de janela LAG() pode retornar qualquer coluna do mês anterior. Vejamos um exemplo que obtém a diferença de receita entre cada par de meses consecutivos. SELECT make, model, month, revenue AS current_month_revenue, LAG(revenue) OVER ( ORDER BY month) AS previous_month_revenue, revenue - LAG (revenue) OVER (ORDER BY month) AS delta_revenue FROM monthly_car_sales WHERE year = 2021 AND model = 'Mustang' O resultado da consulta anterior é: makeModelMonthCurrent Month RevenuePrevious Month RevenueDelta Revenue FordMustang11010000NULLNULL FordMustang2105000010100004000 FordMustang320800001050000103000 FordMustang425200002080000440000 A primeira linha do resultado tem valores NULL nas colunas previous_month_revenue e delta_revenue. Isto porque não há nenhum mês anterior para janeiro. A coluna delta_revenue é calculada entre a receita do mês atual e a receita do mês anterior, a última das quais é obtida com a função da janela LAG(). Quando usamos ORDER BY em uma cláusula OVER, há um novo elemento a ser considerado: os limites da moldura da janela. Se não especificarmos nenhuma cláusula ORDER BY, toda a divisória se torna a moldura da janela. Entretanto, quando usamos uma subcláusula ORDER BY, a linha atual se torna o limite superior da moldura da janela. Em outras palavras, as linhas que seguem a linha atual (com base no critério ORDER BY ) não estão incluídas na moldura da janela. Na próxima seção, abordaremos em detalhes o conceito de limites da moldura da janela. Definindo os limites da moldura de janela com ROWS Uma característica muito interessante da cláusula OVER é a capacidade de especificar os limites superior e inferior de uma moldura de janela. Estes limites podem ser especificados usando uma das duas subcláusulas da cláusula OVER: ROWS ou RANGE. Nesta seção, explicaremos como usar a subcláusula ROWS da cláusula OVER. A moldura da janela é um conjunto de linhas que estão de alguma forma relacionadas com a linha atual. Seus limites podem ser definidos para cada linha no resultado da consulta com uma subcláusula ROWS, que tem a seguinte sintaxe: ROWS BETWEEN lower_bound AND upper_bound Como já mencionamos na seção anterior, é importante saber quais são os limites padrão da moldura da janela. Quando especificamos uma subcláusula ORDER BY, a linha atual é o limite superior da moldura da janela por padrão. Entretanto, em alguns casos, precisamos alterar este limite superior (ou o limite inferior), como veremos abaixo. Vamos ver um exemplo onde precisamos especificar os limites de uma moldura de janela. Suponha que queremos um relatório com o total de vendas do mês atual, o total de vendas do mês anterior e o máximo de vendas em qualquer mês individual ao longo do ano, tudo por marca e modelo. A consulta para obter tal relatório é: SELECT make, model, month, revenue AS current_month_revenue, LAG(revenue) OVER (PARTITION BY make, model ORDER BY month) AS prev_month, MAX(revenue) OVER (PARTITION BY make, model ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS max_year_revenue FROM monthly_car_sales WHERE year = 2021 makemodelmonthcurrent_month_revenueprev_monthmax_year_revenue FordF10012500000NULL2500000 FordF1002120000025000002500000 FordMustang11010000NULL2520000 FordMustang2105000010100002520000 FordMustang3208000010500002520000 FordMustang4252000020800002520000 RenaultFuego19000000NULL23000000 RenaultFuego223000000900000023000000 RenaultKoleos31004000NULL1504000 RenaultKoleos4150400010040001504000 RenaultMegane320000000NULL20000000 RenaultMegane4150000002000000020000000 Se tivéssemos omitido a subcláusula ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING na função da janela MAX() na consulta anterior, teríamos obtido o máximo entre o primeiro mês e o mês atual. Isto está errado, já que queremos a receita mensal máxima considerando o ano inteiro (incluindo os meses após o mês atual). Portanto, precisamos incluir todos os meses disponíveis na tabela. Fazemos isso adicionando a subcláusula ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING à cláusula OVER. A imagem seguinte mostra todos os limites possíveis que podemos especificar para definir os limites inferior e superior de uma moldura de janela: As opções para os limites inferior e superior na cláusula OVER são: UNBOUNDED PRECEDING N PRECEDING CURRENT ROW N FOLLOWING UNBOUNDED FOLLOWING Precisamos ter certeza de que o limite inferior seja menor do que o limite superior. Finalmente, eu gostaria de sugerir o artigo Por que aprender SQL Funções de Janela (Window Functions) em SQL em 2021? onde você pode aprender como usar as funções de janela. Definindo Limites de Janela com RANGE Na seção anterior, definimos os limites de uma moldura de janela em termos de ROWS. Nesta seção, explicaremos como usar a subcláusula RANGE para especificar os limites de uma moldura de janela em intervalos de linhas. A sintaxe da subcláusula RANGE é a seguinte: RANGE BETWEEN lower_bound AND upper_bound Um intervalo é um conjunto de linhas com o mesmo valor para o critério PARTITION BY. Por exemplo, se tivermos um mês PARTITION BY, podemos ver a diferença na próxima imagem quando usamos ROWS ou RANGE para definir uma moldura de janela: OVER ( PARTITION BY …... ORDER BY month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) OVER ( PARTITION BY ….. ORDER BY month RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING ) Se quisermos um relatório de receitas por marca para o mês atual e para cada um dos últimos três meses, podemos usar a seguinte consulta: SELECT make, model, month, revenue AS model_revenue_current_month, SUM(revenue) OVER ( PARTITION BY make ORDER BY month RANGE BETWEEN 0 PRECEDING AND CURRENT ROW ) AS make_current_month, SUM(revenue) OVER (PARTITION BY make ORDER BY month RANGE BETWEEN 1 PRECEDING AND CURRENT ROW ) AS make_last_2_months, SUM(revenue) OVER (PARTITION BY make ORDER BY month RANGE BETWEEN 2 PRECEDING AND CURRENT ROW ) AS make_last_3_months FROM monthly_car_sales WHERE year = 2021 ORDER BY 1,3,2 A consulta anterior usa a subcláusula RANGE para especificar um quadro de janela com todos os registros da marca atual para uma faixa de N meses. Por exemplo: SUM(revenue) OVER ( PARTITION BY make ORDER BY month RANGE BETWEEN 1 PRECEDING AND CURRENT ROW ) AS make_last_2_months A subcláusula anterior RANGE BETWEEN 1 PRECEDING AND CURRENT ROW especifica um quadro de janela que inclui o mês anterior e o mês atual. Então, a função SUM() retornará a receita total nos dois últimos meses. Da mesma forma, podemos usar a seguinte cláusula OVER para obter a receita total nos últimos três meses. SUM(revenue) OVER ( PARTITION BY make ORDER BY month RANGE BETWEEN 2 PRECEDING AND CURRENT ROW ) AS make_last_3_months Há várias abreviações disponíveis para facilitar a sintaxe destas cláusulas limitadoras: AbbreviationComplete Syntax UNBOUNDED PRECEDINGBETWEEN UNBOUNDED PRECEDING AND CURRENT ROW n PRECEDINGBETWEEN n PRECEDING AND CURRENT ROW CURRENT ROWBETWEEN CURRENT ROW AND CURRENT ROW n FOLLOWINGBETWEEN AND CURRENT ROW AND n FOLLOWING UNBOUNDED FOLLOWINGBETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING Por último, mas não menos importante, aqui está a minha folha de consultas preferida nas funções de janela com muitos detalhes de sintaxe: folha de consultas com funções de janela SQL. Aproveite a vantagem de Funções de Janela (Window Functions) em SQL! Uma idéia central na função de janela é a estrutura da janela, ou seja, o grupo de registros sobre o qual a função de janela funciona. Neste artigo, explicamos que a moldura de janela depende da linha atual e é definida pela cláusula OVER. Também mostramos vários exemplos para definir quais registros devem ser incluídos no quadro de janela, ordenando as linhas dentro dele e definindo seus limites. Para aqueles que querem ir mais fundo, sugiro o curso online Funções de Janela (Window Functions) em SQL, com muitos exemplos usando diferentes funções de janela. Desenvolva suas habilidades e aumente seus ativos!! Tags: sql aprender sql window functions