7th Dec 2023 23 minutos de leitura O que são funções de janela do SQL? Tihomir Babic sql window functions Índice Breve histórico do SQL Funções de Janela (Window Functions) em SQL O que é uma Window? Sintaxe da função de janela do SQL Exemplos de conjunto de dados e sintaxe Exemplo de sintaxe nº 1: OVER () Exemplo de sintaxe nº 2: OVER (ORDER BY) Exemplo de sintaxe nº 3: OVER (PARTITION BY) Exemplo de sintaxe nº 4: OVER (ORDER BY PARTITION BY) Quais são as mais comuns Funções de Janela (Window Functions) em SQL? Exemplos de funções de janela SQL do mundo real Exemplo nº 1: Porcentagem do total Função de janela vs. função agregada vs. GROUP BY Resolva este exercício para praticar Exemplo nº 2: dados de classificação Resolva este exercício para praticar Exemplo nº 3: Total em execução Resolva este exercício para praticar Exemplo nº 4: Diferença entre trimestres Resolva este exercício para praticar SQL Funções de Janela (Window Functions) em SQL: Uma janela para uma melhor análise de dados Precisa melhorar seu jogo de análise de dados? Aprenda essas funções de janela SQL aqui e você levará suas habilidades de análise para o próximo nível. Inclui exercícios práticos e explicações detalhadas! Quando ouvi falar pela primeira vez sobre as funções de janela do SQL, pensei que se tratava de um estranho casamento entre o SQL e o Windows. Eu estava errado. As funções de janela do SQL não têm nada a ver com esse famoso sistema operacional. Elas são funções SQL que fazem cálculos no conjunto de linhas relacionadas à linha atual. Esse conjunto de linhas é chamado de janela ou quadro de janela - daí o nome da função. Você também pode ouvir falar de funções de janela no SQL, funções analíticas ou funções OVER(). Todos esses são apenas nomes alternativos para as funções de janela do SQL - um conjunto extremamente útil de ferramentas para análise de dados. Neste artigo, mostraremos o que você pode fazer com as funções de janela e como. Começarei com um breve histórico das funções de janela do SQL e explicarei por que elas têm esse nome. Em seguida, orientarei você pela sintaxe e mostrarei como ela funciona com vários exemplos. Depois de praticar a sintaxe, estaremos prontos para exemplos reais de funções de janela da vida de um analista de dados. E aqui está a parte mais interessante: após cada exemplo, há um exercício para você resolver e aprender por meio da codificação. No entanto, a principal fonte de seu conhecimento sobre esse assunto deve ser o nosso Funções de Janela (Window Functions) em SQL curso. Seus 218 exercícios interativos abrangem detalhadamente as funções de janela do SQL. Em outras palavras, você aprenderá sobre frames de janela e as cláusulas OVER(), PARTITION BY e ORDER BY. Tudo isso é necessário para agregar, classificar e analisar dados usando funções de janela. Breve histórico do SQL Funções de Janela (Window Functions) em SQL As funções de janela foram introduzidas pela primeira vez no banco de dados Oracle8i, que foi lançado em 1998. No entanto, elas foram incluídas no padrão SQL cinco anos depois, com o SQL:2003. Em seguida, a Microsoft as incluiu no SQL Server 2005. Outros sistemas de gerenciamento de banco de dados (DBMS) as seguiram; o PostgreSQL as suporta desde que o PostgreSQL 8.4 foi lançado em 2009; o MariaDB as incluiu na versão 10.2 (2016) e o MySQL as adicionou à versão 8 em 2018. As funções de janela são um recurso bastante novo no SQL. Por esse motivo, elas não fazem parte do currículo normal de SQL. Ao aprendê-las, você estará à frente da curva em comparação com muitos usuários de SQL. O que é uma Window? Um conjunto de linhas relacionadas à linha atual é chamado de janela ou quadro de janela. Daí o nome dessas funções: seu resultado é baseado em um quadro de janela deslizante. Por exemplo, você pode calcular uma soma cumulativa como mostrado abaixo: datesalescumulative_sum 2023-10-014,2414,241 2023-10-022,3896,630 2023-10-031,5808,210 2023-10-043,39511,605 2023-10-051,26512,870 A janela para a soma cumulativa de 2023-10-04 está destacada em verde. Ela inclui a linha atual (para 2023-10-04) e todas as linhas anteriores. Portanto, a soma cumulativa é calculada como a soma de todas as vendas anteriores e atuais: 4.241 + 2.389 + 1.580 + 3.395 = 11.605. (Observe que a linha destacada com pontos vermelhos não está incluída na janela ou na soma). Quando passamos para a próxima linha, a janela também se move: agora ela incluirá todas as linhas anteriores (verde) e a linha atual (pontilhado vermelho). Agora a soma cumulativa é 4.241 + 2.389 + 1.580 + 3.395 + 1.265 = 12.870. Portanto, a janela é o conjunto de linhas relacionadas à linha atual que são usadas em cálculos para essa linha. A janela muda (desliza) à medida que percorremos as linhas; graças a essas imagens de uma janela deslizante, obtemos o nome dessas funções. Sintaxe da função de janela do SQL A sintaxe das funções de janela é a seguinte: SELECT column_1, column_2, <window_function> OVER(PARTITION BY … ORDER BY … ) AS column_alias FROM table; Veja a seguir o que cada parte faz: <window_function> - Especifica a função a ser aplicada a essa janela. OVER() - Define a janela (conjunto de linhas) e indica que se trata de uma função de janela; sem essa cláusula, não se trata de uma função de janela. <window_frame> - Define o tamanho do quadro da janela (opcional). PARTITION BY - Divide a janela em grupos menores chamados partições (opcional); se omitido, todo o conjunto de resultados será uma partição. ORDER BY - Classifica as linhas dentro do quadro da janela (opcional), ou seja, decide em que ordem a operação da janela será executada; se omitida, a ordem das linhas dentro da partição é arbitrária. Cláusulas adicionais podem definir melhor a janela. Sua sintaxe é a seguinte: [<ROWS or RANGE clause> BETWEEN <lower_bound> AND <upper_bound>] A cláusula ROWS define a janela em termos do número fixo de linhas em relação à linha atual. A cláusula RANGE faz o mesmo. Mas também leva em consideração o cálculo de todas as linhas com os mesmos valores nas colunas especificadas na cláusula ORDER BY como a linha atual. Os limites da janela podem ser definidos como UNBOUNDED PRECEDING - Todas as linhas antes da linha atual. n PRECEDING - Um número definido de linhas antes da linha atual. CURRENT ROW - Inclui a linha atual. n FOLLOWING - Um número definido de linhas após a linha atual. UNBOUNDED FOLLOWING - Todas as linhas após a linha atual. Vamos ver agora como isso funciona na prática. Exemplos de conjunto de dados e sintaxe Usaremos a tabela album_catalogue em todos esses exemplos. Você mesmo pode criá-la usando este script. Um instantâneo de dados é mostrado abaixo: idalbum_titlealbum_lengthalbum_genreartistcopies_soldsales_period 1Wednesday Morning, 3 A.M0:31:38FolkSimon & Garfunkel10432022_1Q 2EnRoute: John Scofield Trio LIVE1:13:48JazzJohn Scofield Trio5122022_1Q 3Nasty Gal0:39:15FunkBetty Davis8092022_1Q 4The New Folk Sound of Terry Callier0:37:41FolkTerry Callier9032022_1Q 5In a Silent Way0:38:08JazzMiles Davis4282022_1Q O conjunto de dados é uma lista de álbuns com sua duração, gênero, artista e dados de vendas, incluindo o número de cópias vendidas e o período (trimestres). Os dados vão até o terceiro trimestre de 2023. Primeiro, mostrarei vários exemplos, explicando cada parte crucial da sintaxe das funções de janelamento ao longo do caminho. Exemplo de sintaxe nº 1: OVER () Você pode usar a função de janela SUM() somente com a cláusula OVER() para obter o total de vendas no quarto trimestre de 2022: SELECT sales_period, album_title, artist, copies_sold, SUM (copies_sold) OVER() AS sold_in_4Q_2022 FROM album_catalogue WHERE sales_period = '2022_4Q'; Quero a soma das cópias vendidas, portanto, especifico essa coluna em SUM(). A cláusula OVER() é obrigatória. Se você quiser usar OVER() sem nenhuma das cláusulas opcionais, basta deixar os parênteses vazios. Eu uso WHERE para gerar somente os dados do trimestre desejado. Quando você escreve uma consulta como essa - com um OVER() vazio - todo o conjunto de resultados (colunas selecionadas, filtros aplicados etc.) é levado em consideração ao realizar os cálculos da função de janela. Aqui, o resultado mostra as vendas individuais de cada álbum vendido no quarto trimestre de 2022. Ele também mostra o total de vendas de todos os álbuns vendidos nesse período. sales_periodalbum_titleartistcopies_soldsold_in_4q_2022 2022_4QWednesday Morning, 3 A.MSimon & Garfunkel8097,403 2022_4QEnRoute: John Scofield Trio LIVEJohn Scofield Trio6127,403 2022_4QNasty GalBetty Davis3697,403 2022_4QThe New Folk Sound of Terry CallierTerry Callier2147,403 2022_4QIn a Silent WayMiles Davis657,403 2022_4QCold SweatJames Brown2097,403 2022_4QThe Freewheelin' Bob DylanBob Dylan2467,403 2022_4QMy Favorite ThingsJohn Coltrane3777,403 2022_4QA Whole New ThingSly and the Family Stone8167,403 2022_4QFive Leaves LeftNick Drake4007,403 2022_4QHead HuntersHerbie Hancock4097,403 2022_4QIn the Right PlaceDr. John9127,403 2022_4QBlueJoni Mitchell4127,403 2022_4QConciertoJim Hall6127,403 2022_4QDirty MindPrince9417,403 Com a ajuda de SUM() e OVER(), posso mostrar as vendas de cada álbum individual e o total trimestral. Exemplo de sintaxe nº 2: OVER (ORDER BY) Você pode adicionar cláusulas adicionais dentro da cláusula OVER() para alterar a definição do quadro da janela. Uma dessas cláusulas é ORDER BY. A cláusula ORDER BY define a classificação das linhas em um quadro de janela: as linhas podem ser processadas pela função de janela em uma determinada ordem. Vejamos um exemplo. Você pode calcular a soma cumulativa adicionando ORDER BY à consulta anterior. Neste exemplo, quero ver como o álbum "In the Right Place" é vendido ao longo do tempo e o número cumulativo de álbuns vendidos até um determinado período de tempo. Aqui está a consulta: SELECT sales_period, album_title, artist, copies_sold, SUM (copies_sold) OVER(ORDER BY sales_period ASC) AS cumulative_sum FROM album_catalogue WHERE album_title = 'In the Right Place'; A mesma coluna copies_sold está em SUM(). Desta vez, OVER() contém a cláusula ORDER BY. Você deseja mostrar as vendas cumulativas do primeiro ao último trimestre. É por isso que você precisa de sales_period e ASC em ORDER BY. sales_periodalbum_titleartistcopies_soldcumulative_sum 2022_1QIn the Right PlaceDr. John222222 2022_2QIn the Right PlaceDr. John208430 2022_3QIn the Right PlaceDr. John94524 2022_4QIn the Right PlaceDr. John9121436 2023_1QIn the Right PlaceDr. John9122348 2023_2QIn the Right PlaceDr. John562404 2023_3QIn the Right PlaceDr. John5622966 Em cada linha, você pode ver as vendas de cada trimestre e a soma cumulativa, ou seja, a soma do trimestre atual e de todos os trimestres anteriores. Por exemplo, o álbum vendeu 94 cópias no terceiro trimestre de 2022. O total de vendas em 2022 até então (ou em três trimestres) é: 222 + 208 + 94 = 524. Exemplo de sintaxe nº 3: OVER (PARTITION BY) Outra cláusula que você pode usar em OVER() é PARTITION BY. PARTITION BY é usada para dividir a janela em segmentos menores com base em alguns critérios. Por exemplo, você pode listar os álbuns, seus dados de vendas para o quarto trimestre de 2022 e as vendas por gênero para esse trimestre: SELECT album_title, artist, copies_sold, album_genre, SUM (copies_sold) OVER(PARTITION BY album_genre) AS sales_by_genre FROM album_catalogue WHERE sales_period = '2022_4Q'; Novamente, usamos a mesma função de janela SUM(). Desta vez, porém, usamos PARTITION BY para dividir a janela em segmentos menores com base no gênero do álbum. Todo o resto permanece o mesmo. A consulta retorna o resultado abaixo. Trata-se de uma análise dos dados de vendas de álbuns por gênero no último trimestre de 2022. album_titleartistcopies_soldalbum_genresales_by_genre Wednesday Morning, 3 A.MSimon & Garfunkel809Folk2,081 The Freewheelin' Bob DylanBob Dylan246Folk2,081 Five Leaves LeftNick Drake400Folk2,081 The New Folk Sound of Terry CallierTerry Callier214Folk2,081 BlueJoni Mitchell412Folk2,081 Dirty MindPrince941Funk3,247 Nasty GalBetty Davis369Funk3,247 Cold SweatJames Brown209Funk3,247 A Whole New ThingSly and the Family Stone816Funk3,247 In the Right PlaceDr. John912Funk3,247 Head HuntersHerbie Hancock409Jazz2,075 EnRoute: John Scofield Trio LIVEJohn Scofield Trio612Jazz2,075 In a Silent WayMiles Davis65Jazz2,075 ConciertoJim Hall612Jazz2,075 My Favorite ThingsJohn Coltrane377Jazz2,075 Por exemplo, a soma cumulativa dos álbuns folk é 809 + 246 + 400 + 214 + 412 = 2.081. Exemplo de sintaxe nº 4: OVER (ORDER BY PARTITION BY) Você também pode usar tanto PARTITION BY quanto ORDER BY em OVER(). As linhas são divididas em segmentos com PARTITION BY e processadas em uma determinada ordem por ORDER BY. Usando a consulta abaixo, posso mostrar todos os dados analíticos do álbum e calcular a soma cumulativa de cada álbum separadamente: SELECT sales_period, album_title, artist, copies_sold, SUM (copies_sold) OVER(PARTITION BY album_title ORDER BY sales_period ASC) AS cumulative_sum_by_album FROM album_catalogue; Calculei isso com a ajuda da função de janela SUM(), como fiz anteriormente. Particionei a janela por álbum. Isso significa que a soma será acumulada até que a função atinja a última linha de um determinado álbum. Quando chega a outro álbum, ela reinicia e começa a acumular a soma desde o início. Também uso ORDER BY para instruir a função a acumular a soma do primeiro ao último trimestre. sales_periodalbum_titleartistcopies_soldcumulative_sum_by_album 2022_1QA Whole New ThingSly and the Family Stone674674 2022_2QA Whole New ThingSly and the Family Stone257931 2022_3QA Whole New ThingSly and the Family Stone6661,597 2022_4QA Whole New ThingSly and the Family Stone8162,413 2023_1QA Whole New ThingSly and the Family Stone8163,229 2023_2QA Whole New ThingSly and the Family Stone3023,531 2023_3QA Whole New ThingSly and the Family Stone1233,654 2022_1QBlueJoni Mitchell589589 2022_2QBlueJoni Mitchell184773 2022_3QBlueJoni Mitchell2561,029 2022_4QBlueJoni Mitchell4121,441 2023_1QBlueJoni Mitchell4121,853 2023_2QBlueJoni Mitchell991,952 2023_3QBlueJoni Mitchell9952,947 …………… 2022_1QWednesday Morning, 3 A.MSimon & Garfunkel1,0431,043 2022_2QWednesday Morning, 3 A.MSimon & Garfunkel4371,480 2022_3QWednesday Morning, 3 A.MSimon & Garfunkel1841,664 2022_4QWednesday Morning, 3 A.MSimon & Garfunkel8092,473 2023_1QWednesday Morning, 3 A.MSimon & Garfunkel8093,282 2023_2QWednesday Morning, 3 A.MSimon & Garfunkel3253,607 2023_3QWednesday Morning, 3 A.MSimon & Garfunkel6124,219 Você pode ver que a soma acumulada para "A Whole New Thing" é 3.654. O próximo álbum ("Blue") começa com a próxima linha, portanto, a acumulação é reiniciada: a soma acumulada é a mesma que as vendas individuais do álbum no primeiro trimestre de 2022. Em seguida, ela se acumula até chegar ao próximo álbum. O resultado vai até o último álbum, que é "Wednesday Morning, 3 A.M." em nosso caso. Mostrei a você as formas mais comuns de definir quadros de janelas com esses exemplos. Mas essas não são as únicas maneiras. Você também pode usar as cláusulas ROW ou RANGE com a sintaxe e os limites que explicamos anteriormente. Não se preocupe. Você verá o uso prático disso em exemplos do mundo real. Usei apenas uma função, SUM(), em todos esses exemplos. Essa é uma das muitas funções de janela; vamos revisar rapidamente algumas das outras. Quais são as mais comuns Funções de Janela (Window Functions) em SQL? As funções de janela mais comuns podem ser divididas em três categorias: Agregado Funções de Janela (Window Functions) em SQL: COUNT() - Conta o número de linhas em uma janela. SUM() - Totaliza determinados valores em uma janela. AVG() - Calcula a média de determinados valores em uma janela. MIN() - Localiza o menor valor em uma janela. MAX() - Encontra o maior valor em uma janela. Classificação Funções de Janela (Window Functions) em SQL: ROW_NUMBER() - Classifica os valores sequencialmente, com classificações diferentes para os valores empatados. RANK() - Classifica os valores usando a mesma classificação para os valores empatados; pula a próxima classificação após os empates (por exemplo, 1, 2, 2, 4). DENSE_RANK() - Classifica os valores usando a mesma classificação para os valores empatados; não pula a próxima classificação após os empates (por exemplo, 1,2,2,3,4). Analítico Funções de Janela (Window Functions) em SQL: LEAD() - Obtém dados de um deslocamento definido (ou seja, um número declarado de linhas) após a linha atual. LAG() - Obtém dados de um deslocamento definido (ou seja, um número declarado de linhas) antes da linha atual. Há mais funções de janela que podem ser úteis. Confira-as em nossa Folha de dicas SQL Funções de Janela (Window Functions) em SQL gratuita . Exemplos de funções de janela SQL do mundo real Até agora, concentrei-me mais na sintaxe das funções de janela do SQL. Agora, mostrarei os usos práticos mais comuns das funções de janela e como elas podem ajudar os analistas de dados em seu trabalho. Esses exemplos usarão o mesmo conjunto de dados usado anteriormente. Exemplo nº 1: Porcentagem do total Vamos mostrar informações sobre cada álbum e suas vendas no primeiro trimestre de 2023. Além disso, mostraremos as vendas trimestrais por cada gênero. Em seguida, vamos calcular quanto cada álbum (como porcentagem) contribui para as vendas por gênero. SELECT album_title, artist, copies_sold, album_genre, SUM(copies_sold) OVER (PARTITION BY album_genre) AS sales_by_genre, (copies_sold*1.0/ SUM(copies_sold) OVER (PARTITION BY album_genre))*100.0 AS percent_of_genre_sales FROM album_catalogue WHERE sales_period = '2023_1Q' ORDER BY album_genre, copies_sold DESC; Para obter as vendas por gênero, uso novamente a função de janela SUM(). Na cláusula OVER(), uso apenas PARTITION BY. Dessa forma, posso dividir a janela pelo gênero do álbum. Na próxima linha de código, divido as cópias vendidas (de cada álbum) e divido pelas vendas por gênero. Para fazer isso, basta copiar o cálculo da linha anterior. Em seguida, multiplique o quociente por 100 para obter a porcentagem. Você notará que eu também multipliquei copies_sold por 1,0. Isso serve para converter números inteiros em valores decimais. Filtre o trimestre desejado usando WHERE. Por fim, ordene o resultado em ordem alfabética por gênero e, em seguida, de forma decrescente por cópias vendidas. Aqui está o resultado: album_titleartistcopies_soldalbum_genresales_by_genrepercent_of_genre_sales Wednesday Morning, 3 A.MSimon & Garfunkel809Folk2,08138.88 BlueJoni Mitchell412Folk2,08119.80 Five Leaves LeftNick Drake400Folk2,08119.22 The Freewheelin' Bob DylanBob Dylan246Folk2,08111.82 The New Folk Sound of Terry CallierTerry Callier214Folk2,08110.28 Dirty MindPrince941Funk3,24728.98 In the Right PlaceDr. John912Funk3,24728.09 A Whole New ThingSly and the Family Stone816Funk3,24725.13 Nasty GalBetty Davis369Funk3,24711.36 Cold SweatJames Brown209Funk3,2476.44 EnRoute: John Scofield Trio LIVEJohn Scofield Trio612Jazz2,07529.49 ConciertoJim Hall612Jazz2,07529.49 Head HuntersHerbie Hancock409Jazz2,07519.71 My Favorite ThingsJohn Coltrane377Jazz2,07518.17 In a Silent WayMiles Davis65Jazz2,0753.13 Vamos verificar o cálculo da primeira linha. O álbum de Simon & Garfunkel vendeu 809 cópias. O total de vendas de álbuns folk nesse trimestre foi de 2.081. Portanto, a porcentagem das vendas individuais no total de vendas do gênero é 809/2.081*100 = 38,88%. A soma das porcentagens de cada gênero deve ser 100%. Vamos verificar isso em um gênero folclórico: 38,88% + 19,80% + 19,22% + 11,82% + 10,28% = 100%. Função de janela vs. função agregada vs. GROUP BY Estou novamente usando a função de agregação como uma função de janela. Eu poderia ter usado uma função agregada simples SUM() com GROUP BY para obter as vendas de cada gênero no trimestre especificado. Qual é a diferença, então? Uma função de janela permite mostrar dados analíticos e agregados (vendas individuais com vendas por gênero e o quociente desses valores), enquanto uma função agregada usada com GROUP BY recolheria a linha individual e mostraria somente o valor agregado (a soma das vendas do trimestre). Resolva este exercício para praticar Usando funções de janela, reescreva a consulta acima para que ela mostre a venda média por gênero. Além disso, mostre o quanto as vendas de cada álbum estão acima ou abaixo da média do gênero (em porcentagem). Mostre somente as vendas do terceiro trimestre de 2023. Mostre o título do álbum, o artista, as cópias vendidas e o gênero do álbum. Classifique o resultado de forma ascendente por gênero e vendas de álbuns individuais. Solução: SELECT album_title, artist, copies_sold, album_genre, AVG(copies_sold) OVER (PARTITION BY album_genre) AS average_sales_by_genre, ((copies_sold/AVG(copies_sold) OVER (PARTITION BY album_genre))-1)*100 AS pct_from_average FROM album_catalogue WHERE sales_period = '2023_3Q' ORDER BY album_genre, copies_sold; Saída: album_titleartistcopies_soldalbum_genreaverage_sales_by_genrepct_from_average The New Folk Sound of Terry CallierTerry Callier283Folk561.6-49.61 Five Leaves LeftNick Drake321Folk561.6-42.84 The Freewheelin' Bob DylanBob Dylan597Folk561.66.30 Wednesday Morning, 3 A.MSimon & Garfunkel612Folk561.68.97 BlueJoni Mitchell995Folk561.677.17 A Whole New ThingSly and the Family Stone123Funk533.4-76.94 Dirty MindPrince169Funk533.4-68.32 In the Right PlaceDr. John562Funk533.45.36 Nasty GalBetty Davis808Funk533.451.48 Cold SweatJames Brown1005Funk533.488.41 ConciertoJim Hall263Jazz464-43.32 My Favorite ThingsJohn Coltrane302Jazz464-34.91 EnRoute: John Scofield Trio LIVEJohn Scofield Trio404Jazz464-12.93 Head HuntersHerbie Hancock542Jazz46416.81 In a Silent WayMiles Davis809Jazz46474.35 Exemplo nº 2: dados de classificação Neste exemplo, usarei uma função de janela para classificar os dados. Quero mostrar cada título de álbum distinto e sua duração e classificá-los por duração. O álbum mais longo será classificado em primeiro lugar. SELECT *, RANK() OVER (ORDER BY album_length DESC) AS album_length_rank FROM (SELECT DISTINCT album_title, album_length FROM album_catalogue) AS distinct_album; Vamos começar explicando a subconsulta: nós a usamos para selecionar álbuns distintos e suas durações. Em seguida, usamos a consulta principal para selecionar todos os dados da subconsulta. Agora, use a função de janela RANK() para classificar os álbuns. Você também pode usar outras funções de classificação, dependendo de seus dados e tarefas. Para que a classificação funcione como você deseja, use a cláusula ORDER BY em OVER(). Especifique a coluna pela qual você deseja classificar e em que ordem. Nesse caso, é de forma decrescente por comprimento. Aqui está a classificação: album_titlealbum_lengthalbum_length_rank EnRoute: John Scofield Trio LIVE1:13:481 The Freewheelin' Bob Dylan0:44:142 Head Hunters0:41:523 Five Leaves Left0:41:434 My Favorite Things0:40:255 Nasty Gal0:39:156 In a Silent Way0:38:087 Concierto0:38:028 A Whole New Thing0:38:019 The New Folk Sound of Terry Callier0:37:4110 Blue0:36:1511 Cold Sweat0:33:4312 In the Right Place0:33:2213 Wednesday Morning, 3 A.M0:31:3814 Dirty Mind0:30:1415 Resolva este exercício para praticar Classifique cada álbum único por suas vendas dentro de seu gênero. Mostre somente os dados do primeiro trimestre de 2023. Mostre o título do álbum, suas vendas, o gênero e a classificação. Se houver álbuns com o mesmo número de vendas, classifique-os igualmente e não pule a próxima classificação. Solução: SELECT *, DENSE_RANK() OVER (PARTITION BY album_genre ORDER BY copies_sold DESC) AS album_sales_rank FROM (SELECT DISTINCT album_title, copies_sold, album_genre FROM album_catalogue WHERE sales_period = '2023_1Q') AS distinct_album; Saída: album_titlecopies_soldalbum_genrealbum_sales_rank Wednesday Morning, 3 A.M809Folk1 Blue412Folk2 Five Leaves Left400Folk3 The Freewheelin' Bob Dylan246Folk4 The New Folk Sound of Terry Callier214Folk5 Dirty Mind941Funk1 In the Right Place912Funk2 A Whole New Thing816Funk3 Nasty Gal369Funk4 Cold Sweat209Funk5 EnRoute: John Scofield Trio LIVE612Jazz1 Concierto612Jazz1 Head Hunters409Jazz2 My Favorite Things377Jazz3 In a Silent Way65Jazz4 Exemplo nº 3: Total em execução Neste exemplo, mostrarei o período de vendas de um determinado álbum, o título, o artista e as cópias vendidas. Também adicionarei um total de cópias vendidas que incluirá três linhas: a linha atual e as duas anteriores. A soma deve ser calculada do primeiro ao último trimestre. SELECT sales_period, album_title, artist, copies_sold, SUM(copies_sold) OVER (ORDER BY sales_period ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS sales_running_total FROM album_catalogue WHERE album_title = 'In a Silent Way'; Novamente uso a função de janela SUM(). Em seguida, há um ORDER BY em OVER() para ordenar as vendas de modo que possamos somá-las em ordem crescente. Em seguida, preciso definir o quadro da janela móvel. O total em execução deve incluir a linha atual e as duas linhas anteriores. Esses são os limites inferior e superior especificados na cláusula ROWS. O limite inferior são as duas linhas anteriores, ou seja, BETWEEN 2 PRECEDING. O limite superior é CURRENT ROW. Os dois limites são unidos em um quadro de janela usando a palavra-chave AND. Quero mostrar o cálculo para o álbum "In a Silent Way" de Miles Davis, portanto, filtro os dados usando WHERE. Aqui estão os totais em execução: sales_periodalbum_titleartistcopies_soldsales_running_total 2022_1QIn a Silent WayMiles Davis428428 2022_2QIn a Silent WayMiles Davis1,0531,481 2022_3QIn a Silent WayMiles Davis191,500 2022_4QIn a Silent WayMiles Davis651,137 2023_1QIn a Silent WayMiles Davis65149 2023_2QIn a Silent WayMiles Davis218348 2023_3QIn a Silent WayMiles Davis8091,092 Vamos verificar o resultado e explicar o que é um total em execução. Um total em execução é semelhante a um total cumulativo (ou soma), mas não são a mesma coisa. O total acumulado lhe dará a soma da linha atual e de todas as linhas anteriores, ou seja, o quadro da janela aumenta a cada linha. Um total em execução é uma soma em um quadro de janela definido que permanece com o mesmo tamanho, mas se move a cada linha. Em nosso caso, a janela é definida como a linha atual e as duas linhas anteriores. Dê uma olhada nos valores destacados. O total em execução para o primeiro trimestre de 2022 é 428, o mesmo que a venda individual. Não há linhas anteriores, portanto o total em execução inclui apenas a linha atual. O próximo total em execução é 428 + 1.053 = 1.481. Ele soma a linha atual e a anterior, pois há apenas uma linha anterior. O total em execução para o terceiro trimestre de 2022 é 428 + 1.053 + 19 = 1.500. Essa é a primeira vez que você obtém a janela inteira, ou seja, a linha atual e as duas linhas anteriores. Ao passar para a próxima linha, a janela se moverá, mas seu tamanho permanecerá o mesmo. O total em execução para o trimestre seguinte é 428 + 1.053 + 19 + 65 = 1.137. Novamente, ele envolve a linha atual e as duas linhas anteriores, mas diferentes em comparação com o trimestre. Resolva este exercício para praticar Reescreva a consulta acima para que ela calcule o total acumulado do álbum "The New Folk Sound of Terry Callier". O total acumulado deve ser calculado do primeiro ao último trimestre. Ele deve incluir quatro trimestres: os dois anteriores, o trimestre atual e o seguinte. Além disso, mostre o período de vendas, o título do álbum, o artista e o número de cópias vendidas. Solução: SELECT sales_period, album_title, artist, copies_sold, SUM(copies_sold) OVER (ORDER BY sales_period ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) AS sales_running_total FROM album_catalogue WHERE album_title = 'The New Folk Sound of Terry Callier'; Saída: sales_periodalbum_titleartistcopies_soldsales_running_total 2022_1QThe New Folk Sound of Terry CallierTerry Callier9032,575 2022_2QThe New Folk Sound of Terry CallierTerry Callier4182,789 2022_3QThe New Folk Sound of Terry CallierTerry Callier1,2543,003 2022_4QThe New Folk Sound of Terry CallierTerry Callier2142,641 2023_1QThe New Folk Sound of Terry CallierTerry Callier2142,506 2023_2QThe New Folk Sound of Terry CallierTerry Callier5411,252 2023_3QThe New Folk Sound of Terry CallierTerry Callier2831,038 Exemplo nº 4: Diferença entre trimestres Neste último exemplo, mostrarei como usar as funções de janela para calcular a diferença de vendas entre os trimestres: SELECT *, LAG(quarterly_copies_sold) OVER (ORDER BY sales_period) AS previous_quarter_sales, quarterly_copies_sold - LAG(quarterly_copies_sold) OVER (ORDER BY sales_period) AS quarterly_sales_difference FROM (SELECT sales_period, SUM(copies_sold) AS quarterly_copies_sold FROM album_catalogue GROUP BY sales_period) AS quarterly_sales; Primeiro, escrevo uma subconsulta que calcula o total de vendas de cada trimestre. Uso a função de agregação SUM() e agrupo os resultados pelo período de vendas. Em seguida, seleciono todos os dados da subconsulta na consulta principal. Agora preciso obter as vendas do trimestre anterior. Escreverei a função de janela LAG(), que é usada para acessar os valores das linhas anteriores. O valor que desejo acessar é especificado na função. Nesse caso, são as cópias trimestrais vendidas da subconsulta. Ao definir o argumento offset, a função permite que eu defina até onde quero ir. Como não o defini, o deslocamento padrão é um. Em outras palavras, a função obterá os dados da linha/trimestre anterior. Mas se você quiser retroceder duas linhas/quartos, escreva LAG(quarterly_copies_sold, 2). Também uso ORDER BY em OVER() para garantir que os valores dentro do quadro sejam classificados do trimestre mais antigo para o mais recente. Esse uso da função de janela é para que fique mais claro o que farei na próxima linha de código. É aqui que o cálculo real da comparação entre as vendas do trimestre atual e do trimestre anterior é feito. Agora é simples: subtraia a função de janela definida acima da coluna quarterly_copies_sold. Aqui está o resultado: sales_periodquarterly_copies_soldprevious_quarter_salesquarterly_sales_difference 2022_1Q9,519NULLNULL 2022_2Q7,5819,519-1,938 2022_3Q4,2737,581-3,308 2022_4Q7,4034,2733,130 2023_1Q7,4037,4030 2023_2Q4,9567,403-2,447 2023_3Q7,7954,9562,839 Não há valores anteriores para 2022_1Q, pois não há trimestre anterior. As vendas trimestrais para 2022_2Q são 7.581. As vendas no trimestre anterior foram 9.519. O cálculo mostra que as vendas atuais estão 1.938 cópias (7.581 - 9.519) abaixo das vendas do trimestre anterior. Você pode analisar o restante da produção da mesma forma. Resolva este exercício para praticar Reescreva a consulta acima para que ela mostre a diferença entre as vendas trimestrais em uma base anual - por exemplo, compare o primeiro trimestre de 2023 com o primeiro trimestre de 2022. Mostre o período de vendas, as cópias vendidas no trimestre, as vendas do mesmo trimestre no ano anterior e a diferença ano a ano entre os trimestres. Solução: SELECT *, LAG(quarterly_copies_sold, 4) OVER (ORDER BY sales_period) AS year_over_year_sales, quarterly_copies_sold - LAG(quarterly_copies_sold, 4) OVER (ORDER BY sales_period) AS year_over_year_difference FROM (SELECT sales_period, SUM(copies_sold) AS quarterly_copies_sold FROM album_catalogue GROUP BY sales_period) AS quarterly_sales; Saída: sales_periodquarterly_copies_soldyear_over_year_salesyear_over_year_difference 2022_1Q9,519NULLNULL 2022_2Q7,581NULLNULL 2022_3Q4,273NULLNULL 2022_4Q7,403NULLNULL 2023_1Q7,4039,519-2,116 2023_2Q4,9567,581-2,625 2023_3Q7,7954,2733,522 Se você quiser mais, aqui estão outros exemplos de função de janela. Para materiais práticos, dê uma olhada nestes 11 exercícios de funções de janela do SQL. SQL Funções de Janela (Window Functions) em SQL: Uma janela para uma melhor análise de dados Este foi um artigo bastante abrangente sobre as funções de janela do SQL. Você aprendeu as funções de janela e como funciona cada parte crucial de sua sintaxe. Você também sabe que há várias categorias de funções de janela. As mais comumente usadas são as funções de janela agregadas, de classificação e analíticas. Os exemplos práticos mostraram como as funções de janela podem ser usadas em tarefas comuns de análise de dados. Espero que você não tenha pulado os exercícios do artigo. Se o fez, mais uma vez recomendo que você os resolva. Somente com a prática você poderá realmente entender o que são as funções de janela do SQL. O recurso mais rico para aprender e praticar é o nosso Funções de Janela (Window Functions) em SQL curso. É um curso interativo que tem mais de 200 exercícios práticos e abrange a sintaxe completa das funções de janela. Se você tiver entrevistas de emprego agendadas, não deixe de examinar essas perguntas de entrevista sobre funções de janela SQL. Boa sorte e continue aprendendo SQL! Tags: sql window functions