CodeGym /Cursos /SQL SELF /Erros comuns ao usar funções window

Erros comuns ao usar funções window

SQL SELF
Nível 30 , Lição 4
Disponível

Chegou a hora de falar das tretas que podem rolar quando você mexe com funções window. Como sempre, em programação (e na vida), é melhor aprender com os erros dos outros. Bora analisar os vacilos mais comuns que a galera comete — tanto quem tá começando quanto dev experiente — e aprender a não cair nessas armadilhas.

Erro #1: Uso errado do PARTITION BY

Um dos erros mais frequentes é esquecer ou colocar errado o parâmetro PARTITION BY, principalmente quando você quer separar os dados em grupos. Sem ele, o PostgreSQL vai considerar todas as linhas como um grupão só, e aí o resultado pode ser bem diferente do que você espera.

Imagina que a gente tem uma tabela sales com dados de vendas:

id region month total
1 North 2023-01 1000
2 South 2023-01 800
3 North 2023-02 1200
4 South 2023-02 900

Você quer calcular a soma acumulada (SUM()) das vendas por mês pra cada região. Dá pra escrever uma query assim:

SELECT
    region,
    month,
    SUM(total) OVER (ORDER BY month) AS running_total
FROM 
    sales;

Resultado:

region month running_total
North 2023-01 1000
South 2023-01 1800
North 2023-02 3000
South 2023-02 3900

De primeira parece que tá tudo certo. Mas o resultado não bate com o esperado, porque a soma acumulada tá sendo feita pra todas as linhas, não por região. O problema é que esquecemos de colocar o PARTITION BY region.

Código corrigido:

SELECT 
    region,
    month,
    SUM(total) OVER (PARTITION BY region ORDER BY month) AS running_total
FROM 
    sales;

Resultado:

region month running_total
North 2023-01 1000
North 2023-02 2200
South 2023-01 800
South 2023-02 1700

Agora sim: os dados estão agrupados por região e a soma acumulada é calculada separadamente pra cada uma.

Erro #2: Ordem errada no ORDER BY

ORDER BY dentro do OVER() controla a ordem das linhas dentro da janela. Se você errar a ordem, o resultado pode ficar bem estranho.

Você quer calcular as somas acumuladas das vendas, ordenando por mês decrescente. Dá pra fazer assim:

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month DESC) AS running_total
FROM 
    sales;

Resultado:

month total running_total
2023-02 1200 1200
2023-02 900 2100
2023-01 1000 3100
2023-01 800 3900

Parece certo, mas repara: as linhas estão agrupadas por mês, mas a soma acumulada não tá correta por causa da ordem decrescente. Por isso o resultado fica confuso.

Como corrigir: reescreve a query usando a ordem certa no ORDER BY:

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month ASC) AS running_total
FROM 
    sales;

Erro #3: Usar funções window sem índices

Funções window geralmente trabalham com muitos dados, e se não tiver índice nas colunas chave, a performance pode ir pro saco.

Exemplo: temos uma tabela large_sales com milhões de linhas, e queremos calcular o ranking das vendas:

SELECT
    id,
    total,
    RANK() OVER (ORDER BY total DESC) AS rank
FROM 
    large_sales;

Com poucos dados, a query roda de boa, mas com muita linha pode demorar uma eternidade.

Como resolver: cria um índice na coluna usada no ORDER BY:

CREATE INDEX idx_total ON large_sales(total DESC);

Agora a query vai rodar bem mais rápido.

Erro #4: Não entender o que o ROWS ou RANGE faz

Quando você usa ROWS e RANGE, é importante sacar como eles definem a janela de linhas. Se não entender direito, o resultado pode ser inesperado.

Exemplo: você quer calcular a média móvel das vendas do mês atual e dos dois anteriores:

SELECT
    month,
    AVG(total) OVER (ORDER BY month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

Se em vez de ROWS você usar RANGE:

SELECT
    month,
    AVG(total) OVER (ORDER BY month RANGE BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

O resultado vai ser diferente, porque RANGE trabalha com intervalos de valores, não com quantidade de linhas.

Erro #5: Usar funções window demais

Se você mete várias funções window na mesma query, pode acabar duplicando cálculos e deixando tudo mais lento.

Exemplo:

SELECT 
    id,
    total,
    SUM(total) OVER (PARTITION BY region) AS region_total,
    SUM(total) OVER (PARTITION BY region) / COUNT(total) OVER (PARTITION BY region) AS region_avg
FROM 
    sales;

Aqui o SUM(total) e o COUNT(total) são calculados várias vezes pra cada linha.

Como resolver: simplifica a query usando subquery ou CTE:

WITH cte_region_totals AS (
    SELECT 
        region,
        SUM(total) AS region_total,
        COUNT(total) AS region_count
    FROM 
        sales
    GROUP BY 
        region
)
SELECT 
    s.id,
    s.total,
    t.region_total,
    t.region_total / t.region_count AS region_avg
FROM 
    sales s
JOIN 
    cte_region_totals t ON s.region = t.region;

Dicas pra não vacilar

Confere o PARTITION BY e o ORDER BY: sempre checa se a janela tá definida do jeito certo.

Indexa os dados: principalmente se você usa ordenação (ORDER BY) ou faz filtro.

Usa CTE pra cálculos repetidos: isso ajuda a evitar passos duplicados.

Olha o plano de execução: usa EXPLAIN e EXPLAIN ANALYZE pra entender como o PostgreSQL tá processando sua query.

Testa com dados reais: garante que o resultado bate com o que você espera e resolve o problema certo.

1
Pesquisa/teste
Configurando o frame da janela, nível 30, lição 4
Indisponível
Configurando o frame da janela
Configurando o frame da janela
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION