Agregação e agrupamento em SQL

Aprenda a responder a perguntas de resumo sobre uma tabela de banco de dados: quantos, quanto, qual é a média, o menor e o maior valor. Use COUNT, SUM, AVG, MIN e MAX, agrupe linhas com GROUP BY para obter um resultado por categoria e mantenha apenas os grupos necessários com HAVING. Ao longo do caminho, você aprende como valores ausentes e a divisão de números inteiros alteram os resultados, como arredondar médias e percentuais e como verificar se uma consulta de resumo fornece os números corretos. Os exemplos usam SQL padrão executável no SQLite e no PostgreSQL, com indicações das diferenças no MySQL, SQL Server e Oracle quando forem relevantes.

BásicoAula 4 de 6 do curso Curso de Noções básicas de SQL

O que você vai aprender

  1. Use COUNT, SUM, AVG, MIN e MAX para transformar muitas linhas em valores de resumo, escolha o tipo certo de contagem e preveja como valores ausentes alteram um resultado.
    • Encontrar totais, médias, valores mínimos e máximos
      Use SUM, AVG, MIN e MAX em uma tabela inteira ou nas linhas preservadas por uma cláusula WHERE e combine várias dessas funções em uma consulta.
    • Contar linhas, valores e valores distintos
      Escolha entre COUNT(*), COUNT(column) e COUNT(DISTINCT column) e saiba como cada um trata valores repetidos e ausentes.
    • Prever como os valores NULL afetam as agregações
      Saiba que as funções de agregação ignoram valores NULL, preveja os resultados para conjuntos de entrada vazios e substitua NULL por um valor padrão quando a pergunta exigir.
  2. Use GROUP BY para obter uma linha de resumo por categoria, por combinação de valores ou por valor calculado e siga a regra que determina o que uma consulta agrupada pode exibir.
    • Resumir cada categoria com GROUP BY
      Divida uma tabela em grupos que compartilham um valor, calcule agregações por grupo e ordene e limite o resultado agrupado.
    • Seguir a regra que determina o que uma consulta agrupada pode exibir
      Saiba quais colunas podem aparecer na lista SELECT de uma consulta agrupada, corrija o erro que surge quando a regra é violada e reconheça as diferenças entre bancos de dados.
    • Agrupar por várias colunas e por valores calculados
      Agrupe linhas por combinações de colunas e por expressões, como o mês de uma data ou uma categoria definida por CASE, e interprete o resultado mais detalhado.
  3. Mantenha apenas os grupos cujos totais, contagens ou médias atendem a uma condição e decida se uma condição pertence a WHERE ou a HAVING.
    • Manter os grupos que atendem a uma condição
      Escreva condições HAVING sobre valores agregados, incluindo agregações que não são exibidas, para filtrar um resultado agrupado.
    • Escolher entre WHERE e HAVING
      Use a ordem lógica de uma consulta para decidir se uma condição filtra linhas ou grupos e preveja como essa escolha altera o resultado.
  4. Evite a divisão de números inteiros, saiba qual tipo de número cada função de agregação retorna e arredonde médias, totais e percentuais no momento certo.
    • Evitar a divisão inteira em médias e percentuais
      Reconheça quando a divisão de valores agregados perde as casas decimais, corrija isso com um operando decimal e saiba como os tipos de resultado diferem entre bancos de dados.
    • Arredondar resultados de agregações
      Arredonde médias, totais e percentuais com ROUND, arredonde no momento certo e trate as diferenças entre SQLite e PostgreSQL.
  5. Combine CASE com funções de agregação para obter contagens, totais e percentuais condicionais e transforme uma pergunta em uma consulta agrupada cujos números você possa verificar.
    • Contar e somar por condição com CASE
      Coloque uma expressão CASE dentro de uma função de agregação para calcular várias contagens, totais e percentuais condicionais em uma única consulta agrupada.
    • Construir e verificar uma consulta de resumo a partir de uma pergunta
      Transforme uma pergunta de negócios em uma consulta agrupada passo a passo, evite confundir níveis de detalhe e verifique se os números estão corretos.

Guia de estudo de Agregação e agrupamento em SQL

5 capítulos

1

Resumir dados com funções de agregação

Uma tabela registra eventos individuais; um relatório frequentemente precisa de alguns números que os descrevam em conjunto. Funções de agregação transformam linhas em contagens, totais, médias e valores extremos. Escolher a função é apenas parte do trabalho: você também precisa decidir quais linhas entram no cálculo e o que significam os valores ausentes. Usaremos uma pequena tabela de pedidos para conferir cada resposta à mão antes de confiar na consulta.

1.1 Encontrar totais, médias, valores mínimos e máximos

Uma função de agregação combina valores de várias linhas em um resultado. A Oracle também a chama de função de grupo. Sem GROUP BY, uma consulta de agregação trata todas as linhas que passam por WHERE como um único grupo e retorna uma linha de resumo.

Comece com dados que você pode conferir

Cada linha em orders é um pedido. As colunas numéricas abaixo contêm números inteiros; order_id é a chave primária. As datas usam texto ISO no SQLite e o tipo DATE no PostgreSQL.

order_idcustomerregionamountquantitydiscountorder_date
1AnaEast1202102026-01-05
2BenWest801NULL2026-01-17
3AnaEast45352026-02-02
4ChenNorth2004NULL2026-02-14
5BenWest60102026-02-20
6DaraEast952NULL2026-03-03
7ChenNorth1505152026-03-09
8EliNULL301NULL2026-03-21
Escolha a medida

SUM(amount) soma os valores. AVG(amount) fornece a média aritmética deles. MIN(amount) encontra o menor valor e MAX(amount) encontra o maior. Você pode solicitar as quatro funções em uma consulta:

SELECT SUM(amount) AS total, AVG(amount) AS avg_amount, MIN(amount) AS smallest, MAX(amount) AS largest FROM orders;

O resultado é uma linha: total 780, média 97,5, menor valor 30 e maior valor 200. Some os oito valores para obter 780 e depois divida por oito para obter 97,5. Cada função usa as mesmas oito linhas de entrada. Apelidos claros após AS tornam úteis os cabeçalhos do resultado; um cabeçalho gerado como sum diz pouco sobre o que foi somado.

Filtre antes de calcular

Para resumir os pedidos de East, escreva SELECT COUNT(*) AS orders, SUM(amount) AS total FROM orders WHERE region = 'East';. O filtro mantém os valores 120, 45 e 95. A consulta retorna três pedidos e um total de 260. WHERE escolhe as linhas de entrada antes da execução de qualquer função de agregação.

Uma função de agregação também pode receber uma expressão calculada. Em uma tabela com quantity e unit_price, SUM(quantity * unit_price) primeiro calcula a receita de cada linha e depois as soma. Duas linhas, dois itens a 5 e três itens a 10, contribuem com 10 e 30, para um total de 40. SUM(quantity) * SUM(unit_price) multiplica 5 por 15 e resulta em 75. Manter o cálculo dentro de SUM preserva o preço correspondente a cada quantidade.

Interprete corretamente os valores extremos

MIN(order_date) é 2026-01-05 e MAX(order_date) é 2026-03-21. Valores de data e textos de data ISO são ordenados cronologicamente. Textos como “03/21/2026” seguem a ordem dos caracteres, que não corresponde de forma confiável à ordem das datas. Os valores extremos de texto também seguem a colação do banco de dados, suas regras para comparar textos. Aqui, os clientes extremos são “Ana” e “Eli”; a mistura de maiúsculas e minúsculas pode alterar a ordenação do texto.

MAX(amount) retorna um valor, não o pedido inteiro que o contém. Para mostrar um cliente com um pedido de maior valor, use SELECT customer, amount FROM orders ORDER BY amount DESC LIMIT 1;. O PostgreSQL rejeita uma coluna customer simples ao lado de MAX(amount) sem um agrupamento adequado. O SQLite tem uma regra especial para um único MIN ou MAX que pode retornar uma coluna adjacente da linha com o valor extremo, mas valores extremos empatados ainda precisam de uma regra de desempate.

Principais conclusões

  • Uma função de agregação retorna um valor para um conjunto de linhas.
  • WHERE seleciona as linhas usadas pela função de agregação.
  • Calcule a contribuição de cada linha dentro de SUM quando os valores precisarem permanecer associados.
  • MIN e MAX seguem a ordenação numérica, de datas ou de textos.
  • Um valor extremo não identifica uma linha inteira.

1.2 Contar linhas, valores e valores distintos

“Quantos?” pode ser uma pergunta sobre linhas, valores registrados ou valores diferentes. São contagens diferentes, mesmo quando por acaso resultam no mesmo número em uma tabela pequena.

Três formas de COUNT
ExpressãoO que conta
COUNT(*)Todas as linhas de entrada
COUNT(region)Linhas com região não NULL
COUNT(DISTINCT region)Valores de região diferentes e não NULL

Na tabela de pedidos, as regiões são East, West, East, North, West, East, North e NULL. SELECT COUNT(*) AS order_rows, COUNT(region) AS with_region, COUNT(DISTINCT region) AS regions FROM orders; retorna 8, 7 e 3. Os nomes de região repetidos são contados separadamente em COUNT(region), mas cada nome contribui apenas uma vez para a contagem de valores distintos.

Para “Quantos clientes diferentes fizeram pedidos?”, use COUNT(DISTINCT customer). Ana, Ben e Chen aparecem duas vezes cada, enquanto Dara e Eli aparecem uma vez, então a resposta é cinco clientes. COUNT(customer) retorna oito porque cada pedido identifica um cliente. Essa função conta linhas de pedido com cliente identificado, não pessoas.

Um zero registrado também é contado

Os descontos são 10, NULL, 5, NULL, 0, NULL, 15 e NULL. COUNT(discount) retorna quatro. O zero registra um valor conhecido e é contado assim como 10, 5 e 15. Uma cadeia de caracteres vazia também é um valor no SQLite e no PostgreSQL; o Oracle trata uma cadeia vazia como NULL.

Subtraia a contagem de valores não NULL da contagem de linhas para medir os registros ausentes: SELECT COUNT(*) - COUNT(region) AS missing_region FROM orders; retorna um. Isso funciona porque ambas as contagens usam exatamente as mesmas linhas de entrada.

Listas DISTINCT e contagens de valores distintos

SELECT DISTINCT region FROM orders; lista East, West, North e uma linha NULL. Sua função é retornar valores diferentes, e NULL permanece nessa lista. COUNT(DISTINCT region) retorna três porque a contagem ignora NULL. Não deduza uma contagem de valores distintos contando uma lista sem antes decidir se a linha NULL deve entrar na contagem.

DISTINCT também pode aparecer dentro de SUM ou AVG. As quantidades são 2, 1, 3, 4, 1, 2, 5 e 1. Sua soma comum é 19. SUM(DISTINCT quantity) mantém apenas 1, 2, 3, 4 e 5, resultando em 15. Quantidades repetidas geralmente representam vendas adicionais reais. Removê-las altera a medida; isso não corrige registros duplicados.

Conte combinações em duas etapas

Para pares diferentes de região e cliente, primeiro faça uma lista distinta:

SELECT COUNT(*) FROM (SELECT DISTINCT region, customer FROM orders) AS pairs;

A consulta interna retorna cinco pares: East/Ana, East/Dara, North/Chen, West/Ben e NULL/Eli. O COUNT(*) externo conta essas cinco linhas, incluindo NULL/Eli. Essa forma funciona no SQLite e no PostgreSQL. O MySQL também aceita COUNT(DISTINCT region, customer), mas essa forma exclui combinações que contêm NULL, então pode responder a uma pergunta diferente. No SQLite e no PostgreSQL, a forma com valores separados por vírgula é inválida.

Por fim, uma contagem nunca retorna NULL. SELECT COUNT(*) FROM orders WHERE region = 'South'; retorna uma linha de resumo contendo zero, pois não há pedidos correspondentes.

Principais conclusões

  • Escolha entre linhas, valores registrados e valores registrados diferentes.
  • Zero é um valor registrado, então COUNT(column) o inclui.
  • Uma lista de valores distintos pode incluir NULL; COUNT(DISTINCT column) o ignora.
  • SUM(DISTINCT x) remove valores repetidos, inclusive repetições legítimas.
  • Conte combinações distintas contando as linhas de um resultado interno distinto.
  • COUNT retorna zero para um conjunto de entrada vazio.

1.3 Prever como os valores NULL afetam as agregações

NULL significa que um valor está ausente ou é desconhecido. Isso altera os valores recebidos por uma função de agregação, então um total ou uma média pode ser SQL válido e ainda assim medir algo diferente do que você pretendia.

Determine o denominador

Suponha que scores contenha Ana 80, Ben NULL, Chen 70 e Dara 90. SUM(score) é 240, COUNT(score) é três e COUNT(*) é quatro. AVG(score) é 80: as três notas registradas somam 240 e são divididas por três.

As cinco funções de agregação padrão ignoram argumentos NULL. COUNT(*) conta todas as linhas porque não avalia um argumento de coluna. MIN(score) é 70 e MAX(score) é 90; NULL não se torna a menor nem a maior nota. Isso difere da ordenação, em que valores NULL ocupam uma extremidade do resultado: primeiro em uma ordenação crescente no SQLite, por último em uma ordenação crescente no PostgreSQL.

Uma média calculada manualmente precisa da contagem de valores não NULL: 1.0 * SUM(score) / NULLIF(COUNT(score), 0). O operando decimal preserva resultados fracionários, e NULLIF transforma um divisor zero em NULL. Dividir por COUNT(*) resultaria em 60 e trataria, na prática, a nota ausente como zero.

Decida o que um valor padrão significa

COALESCE retorna seu primeiro argumento não NULL. Se Ben ainda não foi avaliado, mantenha a nota ausente e calcule a média dos resultados conhecidos. Se uma prova perdida é registrada como NULL, mas deve contar como zero, AVG(COALESCE(score, 0)) calcula a média de 80, 0, 70 e 90, resultando em 60. O significado dos dados determina se essa substituição se justifica.

Compare o uso de COALESCE dentro e fora de uma função. AVG(COALESCE(score, 0)) altera os valores que entram na média. COALESCE(AVG(score), 0) altera apenas um resultado final NULL; ainda retorna 80 para essas notas. NVL(x, 0) do Oracle é outra forma com dois argumentos para substituir NULL.

Distinga ausência de linhas de ausência de valores registrados

Com WHERE region = 'South', não restam pedidos. Uma consulta de agregação sem GROUP BY ainda retorna uma linha: COUNT(*) é zero, enquanto SUM(amount), AVG(amount), MIN(amount) e MAX(amount) são NULL. Para exibir um total vazio como zero, use COALESCE(SUM(amount), 0). O SQLite também oferece TOTAL(amount), que retorna 0,0 para um conjunto de entrada vazio.

Agora mantenha os quatro pedidos cujo desconto é NULL. Há linhas, mas não há valores de desconto registrados: COUNT(*) é quatro, COUNT(discount) é zero e SUM(discount) é NULL. Zero valores registrados e quatro valores ausentes são observações diferentes.

Verifique as expressões antes de entrarem em SUM

Operações aritméticas com NULL produzem NULL. Em SUM(amount - discount), os quatro pedidos sem desconto registrado não contribuem com nenhum valor. Apenas as linhas com desconto conhecido contribuem: 110, 40, 60 e 135, totalizando 345.

Se um desconto ausente significa que não há desconto, escreva SUM(amount - COALESCE(discount, 0)). Todos os pedidos passam a contribuir; o valor total de 780 menos os descontos registrados de 30 resulta em 750. Envolver a soma inteira em COALESCE não recuperaria os pedidos omitidos, pois 345 já é um valor não NULL.

Para localizar valores ausentes, use IS NULL ou IS NOT NULL. WHERE discount IS NULL encontra quatro pedidos. discount = NULL nunca é verdadeira e, portanto, não pode selecioná-los.

Principais conclusões

  • AVG(x) divide pela quantidade de valores não NULL.
  • Um COALESCE interno altera os valores de entrada; um externo altera um resultado NULL.
  • Um conjunto de entrada vazio resulta em zero para COUNT e NULL para as outras quatro funções de agregação.
  • NULL dentro de uma expressão aritmética pode excluir a contribuição de uma linha.
2

Agrupar linhas e resumir cada grupo

Um total da tabela inteira responde a uma pergunta, mas muitos relatórios pedem um resultado por cliente, região ou mês. O agrupamento define esse nível de detalhe antes da execução das funções de agregação. Você acompanhará como as linhas se tornam grupos, escolherá colunas que possam descrever um grupo inteiro e verá como adicionar uma coluna de agrupamento altera o relatório. A ordenação determina como apresentar os resultados; o agrupamento por si só não define uma ordem.

2.1 Resumir cada categoria com GROUP BY

GROUP BY reúne linhas que compartilham um valor de agrupamento. Cada função de agregação é executada separadamente dentro de cada grupo, e o resultado contém uma linha para cada grupo existente após a filtragem.

Decida o que uma linha do resultado significa

“Total de vendas por região” pede uma linha de resultado por região. Comece escrevendo essa frase e depois use region como coluna de agrupamento:

SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region;

Os três valores de East, 120, 45 e 95, tornam-se um grupo. Sua contagem é três e seu total é 260. North tem dois pedidos que totalizam 350; West tem dois que totalizam 140. O pedido de Eli forma um grupo de região NULL com um pedido que totaliza 30. Há quatro linhas no resultado, não oito.

Leia a consulta como uma sequência: FROM fornece os pedidos, uma eventual cláusula WHERE remove linhas, GROUP BY reúne as linhas restantes por região e as funções de agregação resumem cada conjunto. SELECT exibe seu rótulo e suas medidas. O agrupamento não descarta os pedidos menores dentro de um grupo; todos contribuem, a menos que um filtro de linha os tenha removido.

Mantenha visíveis as categorias ausentes

Linhas com NULL na coluna de agrupamento pertencem a um único grupo NULL. Isso é útil: um relatório pode mostrar quanta atividade não tem região registrada. Ele não trata cada região ausente como uma categoria diferente.

Para mostrar um rótulo legível, selecione COALESCE(region, 'No region') AS region_label e mantenha GROUP BY region. O rótulo altera o valor exibido. Para excluir essas linhas dos cálculos, adicione WHERE region IS NOT NULL antes de GROUP BY. Os totais resultantes somam 750, pois o valor de 30 de Eli ficou de fora.

Uma consulta agrupada sobre um conjunto de entrada sem linhas não retorna grupos. Por exemplo, filtrar a tabela para South e depois agrupar por região não retorna nenhuma linha de resultado. Isso difere de uma agregação da tabela inteira sem GROUP BY, que produz uma linha de resumo mesmo com um conjunto de entrada vazio.

Ordene os grupos explicitamente

GROUP BY não garante a ordem do resultado. Para listar primeiro as regiões com maiores totais, adicione ORDER BY total DESC. O apelido total é permitido em ORDER BY; ORDER BY SUM(amount) DESC produz a mesma ordenação.

Um relatório de clientes pode selecionar os três maiores totais:

SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer ORDER BY total DESC, customer LIMIT 3;

Ele retorna Chen 350, Ana 165 e Ben 140. A segunda chave de ordenação, customer, dá aos totais empatados uma ordem repetível. LIMIT 3 retorna apenas três linhas; não mantém todos os empates no limite. O SQL Server expressa esse limite com SELECT TOP 3, enquanto o Oracle oferece FETCH FIRST 3 ROWS ONLY.

Ao ordenar rótulos de categoria em ordem crescente, o SQLite normalmente coloca NULL primeiro e o PostgreSQL o coloca por último. Especifique a ordenação desejada quando a posição importar.

Verifique a coluna de agrupamento

SELECT DISTINCT region FROM orders e SELECT region FROM orders GROUP BY region retornam os mesmos rótulos distintos de região, incluindo NULL. Use agrupamento quando também precisar de uma medida para cada rótulo.

Agrupar pela chave única order_id resulta em oito grupos de uma linha cada. Toda contagem é um, e cada total de valor é igual ao valor original. Para um relatório regional, esse resultado indica que a coluna de agrupamento é detalhada demais.

Principais conclusões

  • Diga o que uma linha do resultado representa antes de escolher GROUP BY.
  • Todos os valores NULL de agrupamento formam um único grupo.
  • Use ORDER BY para definir a ordem do resultado e uma segunda chave para desempatar.
  • Agrupar por uma chave única de linha produz grupos de uma linha.

2.2 Seguir a regra que determina o que uma consulta agrupada pode exibir

Um relatório agrupado precisa reunir muitas linhas de entrada em uma linha de resultado. Portanto, cada valor exibido precisa ter um significado claro para o grupo inteiro. Por isso, a SQL restringe as colunas que você pode selecionar.

Siga a regra de agrupamento portável

Um item de um SELECT agrupado deve ser uma coluna de agrupamento, uma expressão construída a partir de colunas de agrupamento, uma função de agregação ou uma constante. Considere:

SELECT region, customer, COUNT(*) FROM orders GROUP BY region;

East contém Ana, Ana e Dara. O grupo tem uma região e uma contagem, mas dois nomes de clientes diferentes. A consulta não informa qual cliente deve ser exibido no único resultado de East. O PostgreSQL rejeita a coluna customer não agrupada.

O mesmo problema surge sem GROUP BY: SELECT customer, SUM(amount) FROM orders combina um total da tabela inteira com um nome individual. O total não tem um único cliente que o identifique.

Corrija a consulta de acordo com a pergunta

Há três correções úteis, cada uma com um significado diferente:

  • Para uma linha por região, remova customer: SELECT region, COUNT(*) FROM orders GROUP BY region;.
  • Para uma linha por região e cliente, agrupe por ambos: SELECT region, customer, COUNT(*) FROM orders GROUP BY region, customer;.
  • Para a quantidade de clientes por região, agregue os nomes: SELECT region, COUNT(DISTINCT customer) AS customers FROM orders GROUP BY region;.

A última consulta apresenta dois clientes em East e um em cada um dos outros grupos de região. Simplesmente adicionar uma coluna a GROUP BY pode alterar o nível de detalhe do relatório, então escolha a correção com base na pergunta, não apenas na mensagem de erro.

Uma coluna de agrupamento pode ser omitida de SELECT. SELECT COUNT(*) FROM orders GROUP BY region; é válida e retorna quatro contagens: três, dois, dois e um, sem ordem garantida. É difícil usar esses números sem os rótulos de região.

Aplique a regra além de SELECT

Um ORDER BY customer em uma consulta agrupada apresenta o mesmo problema quando o agrupamento é feito apenas por região: qual cliente deve determinar a posição de East? Condições HAVING em consultas agrupadas também devem descrever um grupo inteiro. Use nelas colunas agrupadas ou expressões de agregação.

Reconheça o comportamento permissivo de bancos de dados

O SQLite aceita uma coluna não agrupada nem agregada, uma coluna selecionada que não está agrupada nem agregada. Ele obtém um valor de uma linha de entrada do grupo. Um resultado aparentemente válido como “Ana” ao lado de East não significa que Ana represente todos os pedidos dessa região.

Com exatamente uma função de agregação MIN ou MAX incorporada, o SQLite obtém os valores não agrupados nem agregados de uma linha que contém o valor extremo. Empates e várias funções de agregação de extremos tornam incerta a linha selecionada. Esse atalho é específico do banco de dados. Ordenar as linhas originais é mais claro quando você quer um pedido com valor extremo.

O modo padrão ONLY_FULL_GROUP_BY do MySQL rejeita valores não agrupados que não são determinados pelo grupo. ANY_VALUE(customer) permite explicitamente um valor arbitrário, mas não encontra o cliente associado a um total escolhido. SQL Server e Oracle também rejeitam colunas comuns não agrupadas.

PostgreSQL e MySQL reconhecem uma exceção para a chave primária: agrupar pela chave primária de uma tabela identifica uma única linha, então suas outras colunas são determinadas. SELECT order_id, customer, SUM(amount) FROM orders GROUP BY order_id funciona no PostgreSQL. Listar em GROUP BY todas as colunas simples exibidas continua sendo a abordagem portável.

Principais conclusões

  • Cada valor exibido deve descrever o grupo inteiro.
  • Remover, agrupar ou agregar uma coluna responde a perguntas diferentes.
  • A regra de agrupamento também se aplica a HAVING e ORDER BY em consultas agrupadas.
  • Colunas não agrupadas nem agregadas aceitas pelo SQLite podem ocultar um relatório incorreto.
  • Uma chave primária agrupada determina as outras colunas de sua linha.

2.3 Agrupar por várias colunas e por valores calculados

Alguns relatórios precisam de uma combinação de categorias ou de uma categoria calculada a partir de cada linha. A SQL pode agrupar por várias colunas ou por uma expressão. A escolha importante continua sendo o que uma linha do resultado representa.

Agrupe por uma combinação

GROUP BY region, customer reúne linhas apenas quando ambos os valores correspondem. Na tabela de pedidos, execute:

SELECT region, customer, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region, customer ORDER BY region, customer;

Os resultados são East/Ana: dois pedidos, 165; East/Dara: um, 95; North/Chen: dois, 350; West/Ben: dois, 140; e NULL/Eli: um, 30. Os dois resultados de East somam o total regional de 260.

Agrupar por customer, region forma as mesmas combinações. A ordem das colunas em GROUP BY não ordena o resultado. O ORDER BY separado acima escolhe como exibi-lo, sujeito à posição padrão de NULL em cada banco de dados.

Apenas as combinações presentes na entrada aparecem. Não há uma linha West/Ana com contagem zero. O agrupamento resume linhas existentes; não gera todos os pares possíveis de rótulos de categoria.

Adicione detalhes apenas quando necessário

Adicionar uma coluna divide um grupo apenas se suas linhas contiverem valores diferentes nessa coluna. Agrupar apenas por cliente já resulta em cinco grupos neste exemplo. Adicionar a região ainda resulta em cinco, pois cada cliente tem apenas um valor de região. Adicionar order_date a um relatório regional cria grupos menores para as diferentes datas e altera a pergunta respondida.

Agrupe datas por ano e mês

No SQLite, use strftime('%Y-%m', order_date) para criar um rótulo como “2026-02”:

SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY strftime('%Y-%m', order_date) ORDER BY month;

Janeiro tem dois pedidos que totalizam 200, fevereiro tem três que totalizam 305 e março tem três que totalizam 275. No PostgreSQL, substitua as duas ocorrências de strftime('%Y-%m', order_date) por to_char(order_date, 'YYYY-MM') para uma coluna DATE.

Agrupar apenas pelo número do mês combina o mesmo mês de anos diferentes. Janeiro de 2025 e janeiro de 2026 se tornariam um grupo. Manter o ano na expressão de agrupamento preserva os meses de calendário separados.

Repetir a expressão em GROUP BY torna o agrupamento explícito. SQLite, PostgreSQL e MySQL também aceitam o apelido do resultado, como em GROUP BY month; o SQL Server não aceita um apelido de SELECT do mesmo nível nesse ponto.

Crie categorias com CASE

Uma expressão CASE pode atribuir um rótulo a cada pedido antes do agrupamento:

SELECT CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END AS size, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END;

A categoria large contém 120, 200 e 150: três pedidos que totalizam 470. A categoria small contém cinco pedidos que totalizam 310. O limite é inclusivo, então um valor exatamente igual a 100 pertence a “large”. A mesma expressão CASE aparece na exibição e no agrupamento para que ambos usem a mesma definição de categoria.

Principais conclusões

  • Várias colunas de agrupamento identificam combinações que ocorrem nos dados.
  • Adicionar uma coluna divide apenas os grupos em que essa coluna varia.
  • Inclua o ano e o mês para separar os meses do calendário.
  • Use a mesma expressão de categoria no rótulo selecionado e no agrupamento.
  • GROUP BY não cria combinações ausentes com contagem zero.
  • A ordem das colunas de agrupamento não controla a ordem do resultado.
3

Filtrar resultados agrupados com HAVING

A filtragem pode alterar as linhas usadas em um cálculo ou decidir quais resumos concluídos aparecem em um relatório. Essas escolhas respondem a perguntas diferentes. Você usará HAVING para manter grupos por contagem, total ou média e depois o combinará com WHERE sem alterar o significado pretendido. Seguir a ordem lógica de uma consulta facilita posicionar cada condição e prever o resultado antes de executar a SQL.

3.1 Manter os grupos que atendem a uma condição

HAVING testa grupos depois que suas agregações foram calculadas. Use-o para uma solicitação como “regiões com vendas totais acima de 200”. A condição descreve cada total regional, não um pedido individual.

Calcule primeiro, mantenha os grupos depois

SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region HAVING SUM(amount) > 200;

Antes de HAVING, os totais regionais são East 260, North 350, West 140 e NULL 30. A condição mantém East com três pedidos e North com dois. Ela remove os outros dois grupos do resultado; não remove pedidos selecionados de dentro de East ou North.

Na SQL escrita, coloque HAVING depois de GROUP BY e antes de ORDER BY. A ordenação se aplica então aos grupos que passaram pela condição.

Filtre por medidas que você não exibe

SELECT region FROM orders GROUP BY region HAVING COUNT(*) >= 2; retorna East, North e West. O banco de dados pode contar as linhas de um grupo para decidir se ele atende à condição sem exibir essa contagem. HAVING e SELECT não precisam ter listas idênticas de funções de agregação.

Você pode combinar condições de grupo. HAVING COUNT(*) >= 2 AND AVG(amount) > 80 mantém East e North. East tem três pedidos e média de aproximadamente 86,67; North tem dois e média de 175. West tem pedidos suficientes, mas sua média é apenas 70. Ambos os testes devem ser atendidos porque estão ligados por AND; OR permitiria que apenas um deles fosse atendido.

Encontre valores repetidos

Agrupar e contar também encontra duplicatas:

SELECT customer, COUNT(*) AS orders FROM orders GROUP BY customer HAVING COUNT(*) > 1;

Ana, Ben e Chen têm dois pedidos cada e atendem à condição. Dara e Eli têm um e não atendem. Para encontrar valores de e-mail repetidos em uma tabela de clientes, o mesmo padrão agrupa por email e mantém contagens maiores que um. A contagem é o número de registros que compartilham esse valor.

Use a expressão de que a condição precisa

Repita a função de agregação em HAVING: HAVING SUM(amount) > 200. O PostgreSQL e a SQL padrão não permitem o apelido de resultado total nessa condição do mesmo nível, embora SQLite e MySQL permitam. Um apelido pode ser usado com segurança em um ORDER BY total DESC posterior.

Um valor arredondado exibido e o valor testado podem ser diferentes. A média exata de East é 260 dividido por três. Se você selecionar ROUND(AVG(amount), 2), mas escrever HAVING AVG(amount) > 86.67, East será removida: sua média sem arredondamento é inferior a 86,67. North permanece. A condição usa exatamente a expressão escrita em HAVING. Apenas HAVING ROUND(AVG(amount), 2) ... testaria o valor arredondado.

Filtre o único grupo geral

HAVING também pode funcionar sem um GROUP BY explícito. SELECT COUNT(*) FROM orders HAVING COUNT(*) > 5; trata todos os oito pedidos como um grupo, passa no teste e retorna uma linha contendo oito. Substituir a condição por COUNT(*) > 10 não retorna nenhuma linha, não uma linha contendo zero.

O PostgreSQL oferece suporte a esse padrão, assim como o SQLite a partir da versão 3.39.0. Em uma instalação mais antiga do SQLite, uma consulta que usa HAVING precisa de um GROUP BY explícito.

Principais conclusões

  • HAVING mantém ou remove grupos já calculados.
  • Uma função de agregação em HAVING não precisa aparecer em SELECT.
  • Combine testes de grupo com AND, OR e NOT.
  • Repita expressões de agregação em HAVING para obter consultas portáveis.
  • Uma condição testa sua própria expressão, que pode não estar arredondada.

3.2 Escolher entre WHERE e HAVING

Uma condição pertence ao ponto em que aquilo que ela descreve existe. Pedidos individuais existem antes do agrupamento. Um total regional só existe depois que os pedidos foram agrupados e somados.

Acompanhe a ordem lógica

A SQL é escrita como SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. Para raciocinar sobre o resultado, siga esta ordem lógica:

  1. FROM fornece as linhas.
  2. WHERE mantém as linhas que atendem à condição.
  3. GROUP BY forma grupos, e as funções de agregação calculam suas medidas.
  4. HAVING mantém os grupos que atendem à condição.
  5. SELECT produz os valores de saída; DISTINCT remove linhas duplicadas do resultado, se solicitado.
  6. ORDER BY ordena o resultado, e LIMIT mantém a quantidade solicitada de linhas.

O banco de dados pode organizar sua execução interna de outra forma.

Coloque cada condição em seu nível
SolicitaçãoCláusula
Pedidos com amount >= 60WHERE
Pedidos em um determinado intervalo de datasWHERE
Regiões com SUM(amount) > 200HAVING
Clientes com mais de um pedidoHAVING COUNT(*) > 1

WHERE SUM(amount) > 200 falha porque o total ainda não existe na etapa de filtragem de linhas. Uma condição de linha como region = 'East' pode ser avaliada antes do agrupamento e pertence a WHERE.

Acompanhe os dois filtros

SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders WHERE amount >= 60 GROUP BY region HAVING SUM(amount) > 200;

Primeiro, remova os pedidos de 45 e 30. East agora contém 120 e 95, North contém 200 e 150, e West contém 80 e 60. Em seguida, calcule os totais de 215, 350 e 140. Por fim, mantenha os totais acima de 200. O resultado é East com dois pedidos e 215, e North com dois e 350. A região NULL não tem linhas restantes, então nunca forma um grupo.

Não mude a pergunta ao mover um filtro

“Para cada região, calcule a média apenas dos pedidos de 60 ou mais” usa WHERE amount >= 60. A média de East passa a ser 107,5 a partir de 120 e 95.

HAVING MIN(amount) >= 60 pede regiões em que todo valor não NULL atende ao limite. East é removida porque seu mínimo é 45; North e West permanecem com seus pedidos originais. Mover o teste mudou o significado: de selecionar pedidos individuais para aceitar ou rejeitar regiões inteiras.

Para esse relatório regional, region <> 'West' produz o mesmo resultado em WHERE ou HAVING: East e North permanecem, e o grupo NULL também não passa na comparação. WHERE expressa a restrição de linha diretamente e a aplica antes do agrupamento. Para manter também as regiões ausentes, a condição precisa de um OR region IS NULL explícito.

Apelidos de SELECT não estão disponíveis nas cláusulas anteriores WHERE e HAVING no PostgreSQL. O SQLite permite mais usos de apelidos, mas escrever a coluna ou expressão de entrada por extenso deixa clara a etapa pretendida.

Principais conclusões

  • WHERE altera as entradas das funções de agregação; HAVING filtra os resultados das agregações.
  • Coloque condições sobre a contagem, o total ou a média de um grupo em HAVING.
  • Ao prever um resultado, acompanhe a filtragem das linhas antes do agrupamento.
  • Um teste sobre o mínimo do grupo pode remover um grupo inteiro.
4

Calcular resultados exatos e corretamente arredondados

Uma consulta pode escolher as linhas certas e ainda perder a parte fracionária da resposta. Os tipos numéricos controlam a divisão e os resultados das funções de agregação, enquanto o arredondamento controla quanta precisão você exibe. Você preservará as casas decimais nos cálculos, escolherá um tratamento adequado para um denominador vazio e arredondará apenas a medida final. A mesma expressão curta pode se comportar de forma diferente entre bancos de dados, então cada diferença relevante é identificada.

4.1 Evitar a divisão inteira em médias e percentuais

Dividir dois valores inteiros pode descartar a parte fracionária antes mesmo de você exibir a resposta. Isso importa quando você calcula uma média ou um percentual a partir de totais e contagens.

Tenha um operando decimal antes da divisão

No SQLite e no PostgreSQL, 7 / 2 retorna 3. Com valores inteiros de entrada, SUM(quantity) / COUNT(*) na tabela de pedidos retorna 2: 19 itens divididos por oito pedidos perdem a parte fracionária. No PostgreSQL, SUM de uma coluna INTEGER retorna BIGINT, que ainda usa divisão inteira nesse caso.

Escreva 1.0 * SUM(quantity) / COUNT(*) para obter 2,375 nos dois mecanismos. Multiplicar por 1,0 cria um operando decimal antes da divisão. SUM(quantity) / COUNT(*) * 1.0 resulta em 2,0 porque a divisão já descartou a parte fracionária. Operações de mesma precedência são avaliadas da esquerda para a direita.

Para essa tabela, AVG(quantity) fornece diretamente 2,375 no SQLite e no PostgreSQL. A fórmula manual é importante quando você precisa de outro denominador ou de um percentual.

Calcule um percentual

Três dos oito pedidos têm valores de pelo menos 100. A contagem desses pedidos dividida pela contagem de todos os pedidos mede sua proporção. Multiplique por 100,0:

SELECT 100.0 * COUNT(CASE WHEN amount >= 100 THEN 1 END) / COUNT(*) AS pct_large FROM orders;

O resultado é 37,5. Usar o inteiro 100 produz 37 no SQLite e na divisão de contagens inteiras no PostgreSQL. Arredondar depois apenas alteraria a exibição de 37.

Uma consulta sobre a tabela inteira pode não ter linhas correspondentes. NULLIF(COUNT(*), 0) retorna NULL quando a contagem é zero, então 100.0 * COUNT(discount) / NULLIF(COUNT(*), 0) retorna NULL para um conjunto de entrada vazio. Um denominador zero sem tratamento gera erro no PostgreSQL; o SQLite retorna NULL. Uma proporção NULL pode representar claramente “nenhum pedido a medir”.

Verifique o banco de dados e o tipo de entrada
Banco de dadosComportamento a observar
SQLiteA divisão inteira trunca; AVG retorna ponto flutuante.
PostgreSQLA divisão inteira trunca; AVG de entradas inteiras ou NUMERIC retorna NUMERIC.
SQL ServerA divisão inteira trunca; AVG de entradas inteiras retorna um inteiro.
MySQL e Oracle/ mantém o resultado fracionário para operandos inteiros.

No SQL Server, use AVG(quantity * 1.0) ou converta as entradas para DECIMAL antes de calcular a média. No PostgreSQL, SUM de uma coluna BIGINT retorna NUMERIC, então sua divisão não precisa se comportar como SUM de uma coluna INTEGER. O MySQL retorna DECIMAL para somas de entradas inteiras.

Uma conversão também pode criar o operando decimal necessário: use CAST(SUM(quantity) AS REAL) no SQLite ou CAST(SUM(quantity) AS NUMERIC) no PostgreSQL. A conversão para NUMERIC no SQLite pode manter um inteiro, então essa conversão, por si só, não garante divisão decimal.

Distinga decimais exatos de aproximações

Tipos de ponto flutuante armazenam aproximações binárias. NUMERIC e DECIMAL no PostgreSQL oferecem suporte a valores decimais exatos; somas em ponto flutuante podem exibir pequenas imprecisões, como 0,30000000000000004. A afinidade NUMERIC do SQLite não oferece armazenamento decimal exato. Para totais monetários exatos nesse sistema, armazene centavos como inteiros, some-os e divida por 100,0 para exibição.

Principais conclusões

  • Crie um operando decimal antes de dividir totais ou contagens inteiros.
  • Multiplicar após a divisão inteira não recupera os dígitos perdidos.
  • Use NULLIF para tratar um denominador zero.
  • Os tipos de resultado das funções de agregação dependem do mecanismo e do tipo de entrada.
  • A afinidade NUMERIC do SQLite não oferece armazenamento decimal exato.
  • O SQL Server precisa de entradas decimais para obter uma média fracionária de inteiros.

4.2 Arredondar resultados de agregações

O arredondamento determina quantos dígitos um resultado mostra. Mantenha o cálculo completo até a etapa final para que escolhas de exibição não alterem a medida calculada.

Arredonde o resultado de uma agregação

ROUND(x, n) arredonda para n casas após a vírgula decimal. ROUND(x) arredonda para um número inteiro. Por exemplo, ROUND(3.14159, 2) é 3,14.

SELECT region, ROUND(AVG(amount), 2) AS avg_amount FROM orders GROUP BY region; resulta em East 86,67, North 175, West 70 e região NULL 30. O SQLite pode mostrar 175,0, enquanto o resultado NUMERIC do PostgreSQL mostra 175,00. Eles representam o mesmo número. Arredondar um número e formatar um rótulo de texto com largura fixa são tarefas diferentes.

Arredonde depois de somar ou calcular a média

Para três tarifas de 0,44, some primeiro para obter 1,32 e depois arredonde para uma casa decimal para obter 1,3. ROUND(SUM(fee), 1) segue essa sequência. SUM(ROUND(fee, 1)) arredonda cada tarifa para 0,4 e depois as soma, resultando em 1,2. O arredondamento antecipado alterou o total.

Da mesma forma, ROUND(100 * 1 / 3, 1) resulta em 33,0 no SQLite e no PostgreSQL porque a divisão inteira já produziu 33. ROUND(100.0 * 1 / 3, 1) preserva a parte fracionária e resulta em 33,3. Escolha o tipo do cálculo antes de arredondar.

Partes arredondadas podem não somar 100%. Três partes iguais podem ser exibidas como 33,3% cada, totalizando 99,9%. As proporções originais ainda cobrem o todo. Recalcular uma parte arbitrária para forçar o total exibido altera o significado desse número.

Use um tipo de entrada compatível

O PostgreSQL oferece suporte a ROUND(value, n) com dois argumentos para NUMERIC. Se temp for DOUBLE PRECISION, escreva ROUND(CAST(AVG(temp) AS NUMERIC), 2). A média de 20,5, 21,25 e 19,0 é 20,25, e a conversão permite usar o arredondamento com dois argumentos. Com amount inteiro, a média do PostgreSQL já é NUMERIC, então nenhuma conversão é necessária.

Para valores NUMERIC exatos no PostgreSQL, os valores intermediários são arredondados para longe de zero: 2,5 torna-se 3 e -2,5 torna-se -3. O SQLite também retorna 3,0 e -3,0 nesses exemplos. O arredondamento de ponto flutuante no PostgreSQL depende da plataforma; o arredondamento para o par mais próximo é comum. Uma aproximação binária também pode colocar um decimal ligeiramente abaixo do ponto intermediário pretendido. Não use um caso específico de empate em ponto flutuante como regra geral para a aritmética decimal exata.

Observe outras duas diferenças entre dialetos

PostgreSQL, MySQL, SQL Server e Oracle usam uma quantidade negativa de casas decimais para arredondar à esquerda da vírgula. ROUND(1234.5, -2) resulta em 1200. O SQLite trata um segundo argumento negativo como zero e retorna 1235,0. Para arredondar para centenas no SQLite, use ROUND(x / 100.0) * 100.

A conversão para inteiro também depende do banco de dados: o SQLite descarta a parte fracionária, então 2,9 torna-se 2; o PostgreSQL arredonda para 3. Use ROUND quando a finalidade for arredondar. TRUNC(x, n) do PostgreSQL descarta dígitos: TRUNC(2.97, 1) é 2,9, enquanto arredondá-lo para uma casa decimal resulta em 3,0.

Principais conclusões

  • Arredonde o resultado da agregação depois de concluir seu cálculo.
  • O arredondamento não corrige uma divisão inteira anterior.
  • Percentuais arredondados podem totalizar 99,9% ou 100,1%.
  • Converta uma média de ponto flutuante do PostgreSQL para NUMERIC para usar ROUND com dois argumentos.
  • Casas de arredondamento negativas e conversões para inteiro diferem entre bancos de dados.
5

Responder a perguntas de negócios com consultas de resumo

Relatórios de negócios frequentemente precisam de várias medidas da mesma população: todos os pedidos, pedidos de valor alto e a proporção de pedidos de valor alto. A agregação condicional mantém essas medidas lado a lado. Depois, você montará um relatório completo a partir de sua pergunta, verificará totais e categorias ausentes e usará uma segunda etapa de agregação quando a pergunta for sobre clientes ou outros grupos, em vez de pedidos individuais.

5.1 Contar e somar por condição com CASE

A agregação condicional permite que diferentes medidas usem diferentes contribuições, mantendo o mesmo conjunto geral de linhas. Uma expressão CASE determina com o que cada linha contribui para uma contagem ou soma.

Conte as linhas correspondentes

COUNT(CASE WHEN amount >= 100 THEN 1 END) conta pedidos de pelo menos 100. A expressão retorna 1 para uma correspondência e NULL para as outras linhas porque não tem ELSE. COUNT ignora esses valores NULL, restando três correspondências na tabela de pedidos.

SUM(CASE WHEN amount >= 100 THEN 1 ELSE 0 END) conta as correspondências somando uns e zeros. Quando há linhas de entrada, produz a mesma contagem. COUNT(CASE WHEN amount >= 100 THEN 1 ELSE 0 END) não produz: tanto 1 quanto 0 são valores não NULL, então conta todos os oito pedidos.

Some os valores correspondentes

Para um total condicional, retorne o próprio valor:

SELECT region, COUNT(*) AS orders, COUNT(CASE WHEN amount >= 100 THEN 1 END) AS large_orders, SUM(CASE WHEN amount >= 100 THEN amount ELSE 0 END) AS large_total FROM orders GROUP BY region;

East tem três pedidos, um pedido de valor alto e um total de 120 em pedidos de valor alto. North tem dois pedidos, ambos de valor alto, totalizando 350. West tem dois pedidos, nenhum de valor alto e um total de zero em pedidos de valor alto. O grupo de região NULL tem um pedido e zeros para as duas medidas de pedidos de valor alto.

O resultado mantém West porque suas linhas de entrada ainda existem. Adicionar WHERE amount >= 100 removeria as linhas de West antes do agrupamento, então West desapareceria. Esse filtro também faria COUNT(*) contar apenas pedidos de valor alto, perdendo a comparação com todos os pedidos.

Use o denominador correto

Dentro de cada região, calcule o percentual de pedidos de valor alto com ROUND(100.0 * COUNT(CASE WHEN amount >= 100 THEN 1 END) / COUNT(*), 1) AS pct_large. East resulta em 33,3, North em 100,0, West em 0,0 e o grupo NULL em 0,0. Cada denominador é a contagem de pedidos desse grupo, não a contagem de oito da tabela inteira.

Para um relatório sem agrupamento que pode não ter linhas, proteja o denominador com NULLIF(COUNT(*), 0). Uma contagem em um conjunto de entrada vazio é zero, mas um percentual de uma população vazia não tem denominador.

Crie várias colunas de categoria

Um único resultado pode mostrar uma contagem por região:

SELECT COUNT(CASE WHEN region = 'East' THEN 1 END) AS east, COUNT(CASE WHEN region = 'West' THEN 1 END) AS west, COUNT(CASE WHEN region = 'North' THEN 1 END) AS north FROM orders;

As contagens são três, dois e dois. O pedido de Eli não pertence a nenhum desses testes de regiões nomeadas. Adicione COUNT(CASE WHEN region IS NULL THEN 1 END) para contar o único pedido sem região. Comparar uma região NULL com um nome não produz uma condição verdadeira.

Reconheça sintaxes alternativas

O PostgreSQL e o SQLite a partir da versão 3.30.0 oferecem suporte a COUNT(*) FILTER (WHERE amount >= 100). O filtro se aplica a essa função de agregação, então um COUNT(*) adjacente sem filtro ainda conta todos os pedidos. MySQL e SQL Server não oferecem suporte a essa sintaxe FILTER de agregação; a forma com CASE funciona em ambos.

SQLite e MySQL também permitem SUM(amount >= 100) porque as comparações produzem valores lógicos numéricos. O PostgreSQL rejeita SUM de valores booleanos. Use a forma com CASE quando uma consulta precisar funcionar nesses mecanismos.

Principais conclusões

  • Coloque condições dentro das funções de agregação para manter juntas medidas de subconjuntos diferentes.
  • COUNT(CASE ... THEN 1 END) ignora as linhas que não atendem à condição.
  • ELSE 0 funciona em uma soma condicional, mas faz uma contagem condicional contar linhas que não atendem à condição.
  • Um percentual de grupo usa a população desse grupo como denominador.
  • Um FILTER de agregação altera apenas as entradas dessa função de agregação.
  • Use IS NULL para uma contagem separada de categorias ausentes.

5.2 Construir e verificar uma consulta de resumo a partir de uma pergunta

Uma consulta de resumo começa com uma pergunta sobre uma população em um determinado nível de detalhe. Transforme essas escolhas antes de escrever a SQL e depois verifique se o resultado ainda responde à pergunta original.

Construa o relatório em ordem

Pergunte: “Para cada mês de 2026 com pelo menos três pedidos, quantos pedidos foram feitos e qual foi o valor médio, com duas casas decimais?”

  1. As medidas são COUNT(*) e AVG(amount).
  2. A granularidade, ou o significado de uma linha do resultado, é um mês do calendário.
  3. A condição de linha mantém datas em 2026.
  4. A condição de grupo exige pelo menos três pedidos.
  5. O resultado deve ser ordenado por mês, com a média arredondada para exibição.

No SQLite:

SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS orders, ROUND(AVG(amount), 2) AS avg_amount FROM orders WHERE order_date >= '2026-01-01' AND order_date < '2027-01-01' GROUP BY strftime('%Y-%m', order_date) HAVING COUNT(*) >= 3 ORDER BY month;

Para valores de data no PostgreSQL, substitua a expressão de mês nos dois pontos por to_char(order_date, 'YYYY-MM'). O intervalo de datas inclui o início de 2026 e exclui o início de 2027.

Janeiro tem dois pedidos e não atende à condição de grupo. Fevereiro tem três pedidos que totalizam 305, com média de 101,67. Março tem três que totalizam 275, com média de 91,67. Os grupos mantidos correspondem a seis pedidos, não oito, porque HAVING removeu janeiro.

Verifique antes de filtrar os grupos

Execute primeiro o relatório sem HAVING. As contagens de todos os grupos devem somar a quantidade de linhas sob o mesmo filtro WHERE, e os totais devem somar o total sem agrupamento. Aqui, essas verificações resultam em oito e 780. Não compare os totais dos grupos mantidos com toda a entrada depois que alguns grupos forem excluídos.

Procure um grupo NULL, examine a ordem dos resultados e recalcule um grupo filtrando a tabela original. Para East, WHERE region = 'East' deve resultar em três pedidos que totalizam 260. Uma diferença pode revelar uma coluna de agrupamento extra, um filtro de linha mal posicionado ou uma expressão que se tornou NULL.

Distinga a média por pedido da média por cliente

AVG(amount) é 97,5 por pedido. O gasto médio por cliente pede uma unidade diferente: os cinco totais por cliente são 165, 140, 350, 95 e 30. Sua média é 156.

Calcule isso em duas etapas:

SELECT AVG(total) AS avg_customer_total FROM (SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer) AS per_customer;

A consulta interna cria uma linha por cliente. A consulta externa calcula a média dessas linhas, dando a cada cliente uma contribuição. Com todos os clientes identificados, 1.0 * SUM(amount) / COUNT(DISTINCT customer) produz os mesmos 156. Quantidades diferentes de pedidos fazem da média dos valores por pedido um cálculo diferente.

Resuma os próprios grupos

Para contar clientes com mais de um pedido, primeiro liste-os e depois conte suas linhas:

SELECT COUNT(*) FROM (SELECT customer FROM orders GROUP BY customer HAVING COUNT(*) > 1) AS repeat_customers;

A resposta é três. Aninhar funções de agregação diretamente, como em MAX(AVG(amount)) em um único nível de consulta, falha no SQLite e no PostgreSQL. Para encontrar a região com a maior média, ordene as médias agrupadas: ORDER BY AVG(amount) DESC LIMIT 1 retorna North com 175. O Oracle também oferece suporte a funções de grupo aninhadas, mas um nível de consulta separado torna explícitos os dois cálculos. Verifique os empates quando um relatório pedir o maior resultado.

Principais conclusões

  • Escolha medidas, granularidade, condições de linha e condições de grupo a partir da pergunta.
  • Verifique contagens e totais dos grupos antes de removê-los com HAVING.
  • Uma média por cliente precisa dos totais por cliente como entradas.
  • Use uma consulta interna agrupada e uma função de agregação externa para resumir grupos.

Exercícios resolvidos de Agregação e agrupamento em SQL

5 Lições Interativas

1

Transformar linhas de pedidos em números de resumo confiáveis

13 passos
Escolha funções de agregação e contagens e acompanhe os efeitos dos valores ausentes.
  1. 1
    IntroduçãoLeia a pergunta do relatório

    Uma pessoa gerente quer um total de pedidos, uma contagem de clientes e um desconto médio. Cada um parece um número simples, mas cada um usa a entrada de maneira diferente. Cada um é um agregado, que transforma muitas linhas em um valor, e a escolha errada produz um número enganoso. Construiremos essas medidas a partir dos oito pedidos: primeiro combinaremos os valores, depois escolheremos o que contar e, por fim, decidiremos como NULL altera a média. Continue perguntando com o que cada linha de entrada contribui para o resultado.

  2. 2
    ExplicaçãoCombine os valores

    Uma função de agregação combina valores de várias linhas em um resumo. SUM(amount) soma os valores, AVG(amount) encontra sua média e MIN(amount) e MAX(amount) localizam os extremos. Sem GROUP BY, todos os pedidos que atendem à condição formam um grupo. Você pode selecionar várias funções de agregação juntas porque cada uma descreve o mesmo grupo de linhas de entrada.

  3. 3
    ExemploCalcule um resumo completo

    Os valores dos pedidos são 120, 80, 45, 200, 60, 95, 150 e 30. Eles totalizam 780. Dividir esse total por oito resulta em média de 97,5; o menor valor é 30 e o maior é 200.

    SELECT SUM(amount) AS total, AVG(amount) AS mean_amount, MIN(amount) AS low, MAX(amount) AS high FROM orders;

    O resultado é uma linha com quatro medidas identificadas.

  4. 4
    ExemploEscolha a entrada antes de somar

    Agora pergunte apenas sobre East. WHERE region = 'East' mantém os valores 120, 45 e 95 antes da execução da função de agregação.

    SELECT SUM(amount) AS total FROM orders WHERE region = 'East';

    O resultado é 260. As outras regiões não contribuem com nada porque seus pedidos não atenderam à condição de linha. Um filtro nas linhas de entrada altera o próprio total, não apenas seu rótulo exibido.

  5. 5
    DesafioMantenha uma quantidade associada ao seu preço

    Uma tabela de vendas tem duas linhas: quantidade 4 ao preço unitário de 6 e quantidade 2 ao preço unitário de 9. O que SUM(quantity * unit_price) retorna e por que multiplicar as duas somas produz um resultado diferente?

    ---reveal---

    As receitas das linhas são 24 e 18, então a soma é 42. Multiplicar as somas resulta em seis vezes 15, ou 90, porque isso não associa mais cada quantidade ao preço de sua própria linha.

  6. 6
    ExplicaçãoConte registros ou clientes

    Os pedidos identificam Ana, Ben, Ana, Chen, Ben, Dara, Chen e Eli. COUNT(customer) conta oito nomes registrados, incluindo aparições repetidas. COUNT(DISTINCT customer) conta cinco nomes diferentes.

    A pergunta determina qual contagem usar: uma contagem de pedidos precisa de linhas, enquanto uma contagem de clientes precisa de clientes distintos. Nomes iguais em pedidos separados são repetições esperadas, não clientes adicionais.

  7. 7
    ExemploConte a categoria ausente

    A coluna de região tem oito linhas, mas apenas sete valores registrados. COUNT(*) é oito, COUNT(region) é sete e COUNT(DISTINCT region) é três.

    Subtrair a contagem de valores registrados da contagem de linhas resulta em uma região ausente. Observe que uma lista de regiões distintas também incluiria uma linha NULL; a contagem de valores distintos ignora esse NULL em vez de tratá-lo como uma quarta região nomeada.

  8. 8
    DesafioEscolha a contagem certa

    Uma coluna de cupons contém NULL, 0, 8, 8 e 0. Que valores COUNT(*), COUNT(coupon) e COUNT(DISTINCT coupon) retornam, nessa ordem?

    ---reveal---

    Eles retornam cinco, quatro e dois. Há cinco linhas, quatro valores registrados e dois valores registrados diferentes, 0 e 8. Valores zero registrados são contados; NULL não entra em nenhuma das contagens da coluna.

  9. 9
    ExplicaçãoDeixe uma nota desconhecida de fora

    Considere as notas 80, NULL, 70 e 90. As notas registradas totalizam 240. AVG(score) divide pelas três notas registradas e retorna 80.

    A função não divide por todas as quatro linhas: uma nota ausente não é um zero conhecido. Se o valor ausente representa uma prova perdida que deve receber nota zero, o cálculo pretendido muda para AVG(COALESCE(score, 0)), que resulta em 60.

  10. 10
    ExemploColoque o valor padrão na etapa certa

    O desconto está ausente em quatro pedidos. Em SUM(amount - discount), cada uma dessas expressões de linha se torna NULL, então apenas as outras quatro contribuem. Seus valores líquidos totalizam 345.

    Se ausente significa que não há desconto, use SUM(amount - COALESCE(discount, 0)). Todos os oito pedidos passam a contribuir, e o total é 750. COALESCE ao redor da soma concluída não pode recuperar as contribuições das linhas omitidas.

  11. 11
    DesafioTrate um grupo sem valores conhecidos

    Uma consulta mantém três linhas cujos valores são todos NULL. O que COUNT(*), COUNT(amount) e SUM(amount) retornam?

    ---reveal---

    Eles retornam três, zero e NULL. Existem linhas, mas não há valores registrados para contar ou somar. Um conjunto de entrada vazio também produziria uma soma NULL, mas sua contagem de linhas seria zero. Use COALESCE(SUM(amount), 0) apenas quando o relatório deve mostrar esse total ausente como zero.

  12. 12
    DesafioVerifique um cálculo e sua população

    Quatro registros de serviços têm cobranças de 20, 30, 40 e 50, com créditos de 2, NULL, 0 e NULL. Um crédito ausente significa que não há crédito. Qual total líquido de cobranças e qual contagem de créditos registrados o relatório deve mostrar?

    ---reveal---

    Use SUM(charge - COALESCE(credit, 0)) para obter um total líquido de 138 e COUNT(credit) para obter dois créditos registrados. O crédito zero conta como registrado; substituir NULL dentro da soma mantém as quatro cobranças.

  13. 13
    RecapitulaçãoMantenha a medida ligada às suas entradas

    Escolha a função de agregação a partir da pergunta e depois acompanhe os valores que entram nela. As contagens distinguem linhas, valores registrados e valores diferentes. Para médias e operações aritméticas por linha, verifique o que NULL remove e se uma substituição tem um significado real. Quando uma resposta parecer surpreendente, examine as linhas restantes e suas contribuições antes de alterar a SQL.

2

Construir um relatório no nível certo de detalhe

14 passos
Agrupe por categorias, corrija colunas ambíguas e crie grupos combinados ou calculados.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoDecida o que uma linha do resultado representa
  2. 2
    ExplicaçãoReúna linhas por região
  3. 3
    ExemploMantenha o grupo NULL visível
  4. 4
    DicaOrdene antes de manter as primeiras linhas
  5. 5
    DesafioPreveja quantos grupos restam
  6. 6
    ExplicaçãoExplique por que um nome é ambíguo
  7. 7
    ExemploCorrija o relatório a partir da pergunta
  8. 8
    DicaReconheça um resultado permissivo
  9. 9
    DesafioEscolha uma correção significativa
  10. 10
    ExemploDivida um grupo por um segundo valor
  11. 11
    ExplicaçãoCrie um rótulo de mês do calendário
  12. 12
    DesafioEncontre a expressão de agrupamento
  13. 13
    DesafioVerifique a granularidade e os rótulos do relatório
  14. 14
    RecapitulaçãoInterprete cada linha como um grupo
3

Posicionar filtros antes ou depois da agregação

10 passos
Acompanhe WHERE e HAVING em um relatório e preveja como seu posicionamento altera a resposta.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoSepare população de seleção
  2. 2
    ExplicaçãoTeste o grupo concluído
  3. 3
    ExemploUse uma contagem sem exibi-la
  4. 4
    DesafioVerifique o valor efetivamente comparado
  5. 5
    ExplicaçãoAcompanhe as etapas lógicas do resultado
  6. 6
    ExemploRemova primeiro os pedidos menores
  7. 7
    ExemploDepois remova os totais menores de grupos
  8. 8
    DesafioIdentifique uma pergunta alterada
  9. 9
    DesafioCombine restrições de linha e de grupo
  10. 10
    RecapitulaçãoDeixe a condição indicar sua etapa
4

Preservar frações e arredondar o resultado final

11 passos
Acompanhe os tipos numéricos, evite denominadores zero e arredonde agregações na etapa certa.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoSepare cálculo de exibição
  2. 2
    ExemploEncontre onde a fração desaparece
  3. 3
    ExplicaçãoIntroduza o decimal cedo
  4. 4
    DicaTrate um denominador vazio
  5. 5
    DesafioCorrija uma expressão de percentual
  6. 6
    ExplicaçãoArredonde a média calculada
  7. 7
    ExemploVeja o arredondamento antecipado alterar um total
  8. 8
    DesafioVerifique uma diferença entre dialetos
  9. 9
    ConexãoEscolha o tipo para valores exatos
  10. 10
    DesafioVerifique o tipo antes de arredondar
  11. 11
    RecapitulaçãoAcompanhe o número em cada etapa
5

Construir e verificar um resumo de negócios

13 passos
Crie medidas de subconjuntos, escolha a granularidade de um relatório e resuma resultados agrupados em dois níveis de consulta.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoMantenha juntos todos os pedidos e os pedidos selecionados
  2. 2
    ExplicaçãoFaça as linhas sem correspondência contribuírem com NULL
  3. 3
    ExemploMantenha o grupo inteiro disponível
  4. 4
    ExemploSome o valor ou some um
  5. 5
    DesafioPreserve o denominador de um subconjunto
  6. 6
    ExplicaçãoTransforme a pergunta de negócios
  7. 7
    ExemploConstrua o resultado mensal
  8. 8
    DicaVerifique antes de ocultar grupos
  9. 9
    ExplicaçãoAltere a unidade de entrada de uma média
  10. 10
    ExemploInterprete os dois níveis de consulta
  11. 11
    DesafioEscolha a unidade certa para a média
  12. 12
    DesafioConte apenas os grupos de clientes que atendem à condição
  13. 13
    RecapitulaçãoVerifique a população e a granularidade

Questões de Agregação e agrupamento em SQL

40 Questões de Prática em 4 conjuntos

Conjunto 1: Interpretar contagens, grupos e cálculos10 Questões de Prática

Questão 1 de 10

Uma tabela de entregas registra as distâncias 14, 22 e 35. Qual valor SUM(distance) retorna?
  1. 35
  2. 23.67
  3. 71
  4. 3
Mostrar respostaOcultar resposta
Resposta: C
SUM soma as três distâncias, resultando em 71. A maior distância, 35, seria o resultado de MAX(distance), enquanto uma média dividiria a distância combinada por três; nenhuma das duas responde à solicitação de um total.

Questão 2 de 10

Cinco solicitações têm os valores de status closed, open, closed, open e open. O que COUNT(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) retorna?
  1. 5
  2. 2
  3. 3
  4. 0
Mostrar respostaOcultar resposta
Resposta: A
Cada resultado de CASE é um valor registrado: solicitações closed produzem 1 e solicitações open produzem 0. COUNT conta ambos, resultando em cinco. Para contar apenas as duas solicitações closed, omita ELSE para que as linhas sem correspondência produzam NULL ou some os indicadores de um e zero com SUM.

Questão 3 de 10

Quatro entregas têm atrasos de 6, NULL, 10 e 8 minutos. Um atraso ausente significa que ele não foi medido. Qual média AVG(delay) retorna?
  1. 6
  2. 24
  3. 10
  4. 8
Mostrar respostaOcultar resposta
Resposta: D
Os três atrasos medidos totalizam 24 minutos, e AVG divide pela contagem de três, resultando em oito minutos. Dividir pelas quatro linhas resultaria em seis minutos, substituindo na prática o atraso desconhecido por zero, embora nenhuma medição desse tipo tenha sido registrada.

Questão 4 de 10

Uma tabela de turnos contém os valores de departamento Sales, Support, Sales, NULL e NULL. Quantas linhas SELECT department, COUNT(*) FROM shifts GROUP BY department retorna?
  1. 5
  2. 3
  3. 2
  4. 4
Mostrar respostaOcultar resposta
Resposta: B
A consulta forma um grupo para Sales, um para Support e um para o valor de departamento ausente, então retorna três linhas. Valores NULL de agrupamento ficam juntos; tratar cada NULL como um grupo separado criaria uma linha extra de resultado que a SQL não produz.

Questão 5 de 10

Uma tabela de peças tem vários fornecedores por categoria. O relatório precisa de uma linha por categoria e da quantidade de fornecedores diferentes dela. Qual lista SELECT é adequada para FROM parts GROUP BY category?
  1. category, supplier, COUNT(*)
  2. category, COUNT(DISTINCT supplier)
  3. category, COUNT(supplier)
  4. category, MIN(supplier)
Mostrar respostaOcultar resposta
Resposta: B
COUNT(DISTINCT supplier) transforma todos os valores de fornecedor registrados em uma categoria em uma contagem de fornecedores diferentes. Um valor simples de fornecedor é ambíguo porque a categoria pode ter vários. COUNT(supplier) contaria registros com fornecedor, incluindo aparições repetidas.

Questão 6 de 10

Uma tabela de pagamentos do PostgreSQL tem uma coluna DATE paid_on com registros de 2024 a 2026. Qual expressão de agrupamento mantém cada mês do calendário separado?
  1. EXTRACT(MONTH FROM paid_on)
  2. EXTRACT(YEAR FROM paid_on)
  3. paid_on
  4. to_char(paid_on, 'YYYY-MM')
Mostrar respostaOcultar resposta
Resposta: D
A expressão de ano e mês dá a cada mês do calendário sua própria chave, mantendo separados os meses de junho de anos diferentes. Apenas o número do mês reuniria esses meses de junho, enquanto agrupar pela data completa dividiria um mês em grupos diários e alteraria o nível de detalhe solicitado.

Questão 7 de 10

Um relatório agrupado tem os totais por equipe Red 180, Blue 260 e Green 200. Quais equipes permanecem após HAVING SUM(amount) > 200?
  1. Blue
  2. Blue e Green
  3. Red e Blue
  4. Green
Mostrar respostaOcultar resposta
Resposta: A
Apenas Blue tem um total estritamente acima de 200. Green é igual ao limite e, portanto, não passa no teste de maior que; passaria em >= 200. HAVING aplica essa comparação a cada total de equipe concluído, mantendo ou removendo o resultado inteiro de cada equipe.

Questão 8 de 10

Uma consulta do PostgreSQL seleciona categoria e custo total, agrupa apenas por categoria e usa ORDER BY supplier. As categorias têm vários fornecedores. Como ela pode mostrar primeiro as categorias de maior custo sem alterar sua granularidade?
  1. Adicione fornecedor a GROUP BY.
  2. Use ORDER BY supplier DESC.
  3. Use ORDER BY SUM(cost) DESC.
  4. Adicione fornecedor à lista SELECT.
Mostrar respostaOcultar resposta
Resposta: C
Ordenar por SUM(cost) usa uma medida definida para cada grupo de categoria e mantém uma linha por categoria. Um fornecedor simples não pode ordenar um grupo que contém vários fornecedores. Adicionar fornecedor a GROUP BY tornaria a sintaxe válida, mas dividiria as categorias, alterando o detalhe solicitado do relatório.

Questão 9 de 10

No SQLite, quantidades inteiras totalizam 23 em seis linhas. O que SUM(quantity) / COUNT(*) * 1.0 retorna?
  1. 3.0
  2. 3.8333333333333335
  3. 4.0
  4. 23.0
Mostrar respostaOcultar resposta
Resposta: A
A divisão inteira acontece primeiro: 23 dividido por seis é truncado para três. Multiplicar esse resultado por 1,0 produz 3,0 e não pode recuperar a fração perdida. Para manter a média fracionária, introduza o operando decimal antes da divisão com 1.0 * SUM(quantity) / COUNT(*).

Questão 10 de 10

Uma tabela do SQLite tem três tarifas de 0,26. Uma consulta seleciona ROUND(SUM(fee), 1), mas mantém o grupo geral apenas com HAVING SUM(fee) >= 0.8. Qual resultado ela retorna?
  1. Uma linha contendo 0,8.
  2. Uma linha contendo 0,9.
  3. Uma linha contendo NULL.
  4. Nenhuma linha.
Mostrar respostaOcultar resposta
Resposta: D
As tarifas totalizam 0,78, que seria exibido como 0,8 após o arredondamento. HAVING compara a soma sem arredondamento com 0,8, então o grupo não atende à condição e nenhuma linha aparece. Tratar o valor arredondado exibido como o valor testado aceitaria um grupo cujo total real está abaixo do limite.
Conjunto 2: Escolher a população e o detalhe do relatório10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma tabela de chamados tem os valores de prioridade 0, NULL, 2, 2 e NULL. O que COUNT(priority) retorna?
  1. 5
  2. 3
  3. 2
  4. 1
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma tabela work_log tem as colunas consultant, year e hours. Um relatório precisa de um total de horas por consultor em 2025, mantendo apenas totais acima de 120. Qual estrutura de consulta responde à pergunta?
  1. WHERE year = 2025 AND hours > 120 GROUP BY consultant
  2. GROUP BY consultant, hours HAVING SUM(hours) > 120
  3. WHERE hours > 120 GROUP BY consultant, year
  4. WHERE year = 2025 GROUP BY consultant HAVING SUM(hours) > 120
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma tabela armazena datas de entrega como texto ISO: “2025-12-28”, “2026-01-04” e “2025-02-19”. O que MIN(delivery_date) e MAX(delivery_date) retornam, nessa ordem?
  1. 2025-02-19 e 2026-01-04
  2. 2025-12-28 e 2026-01-04
  3. 2026-01-04 e 2025-02-19
  4. 2026-01-04 e 2025-12-28
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Uma tabela do SQLite tem os pares (city, agent) (A, Jo), (A, Jo), (A, Kai), (NULL, Lee) e (NULL, Lee). O que SELECT COUNT(*) FROM (SELECT DISTINCT city, agent FROM visits) AS pairs retorna?
  1. 2
  2. 4
  3. 3
  4. 5
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Quatro reparos têm os valores (cost, credit) (50, 5), (80, NULL), (40, 0) e (30, NULL). NULL significa ausência de crédito. Quais são SUM(cost - credit) e o custo líquido total pretendido, nessa ordem?
  1. 195 e 195
  2. 85 e 85
  3. 115 e 195
  4. 85 e 195
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Os totais por cliente são Ali 90, Bea 120, Cam 120 e Dev 75. Quais linhas ORDER BY total DESC, customer ASC LIMIT 2 mantém, supondo que os nomes sejam ordenados alfabeticamente?
  1. Ali 90 e Bea 120
  2. Bea 120 e Cam 120
  3. Cam 120 e Bea 120
  4. Bea 120 e Ali 90
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Uma tabela de tarifas contém três valores de 0,36. O que ROUND(SUM(fee), 1) e SUM(ROUND(fee, 1)) produzem, nessa ordem, ignorando pequenas imprecisões de exibição de ponto flutuante?
  1. 1,2 e 1,1
  2. 1,1 e 1,1
  3. 1,1 e 1,2
  4. 1,2 e 1,2
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Uma tabela contém os pares (site, worker) (A, Ren), (A, Ren), (A, Sol), (B, Ren), (NULL, Sol) e (NULL, Sol). Quantos grupos resultam do agrupamento por site e, depois, por site e worker?
  1. 3 e 4
  2. 3 e 6
  3. 2 e 3
  4. 3 e 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma lista contém os valores de treinamento Safety, Safety, Tools, Tools, Tools e First Aid. O que SELECT training FROM roster GROUP BY training HAVING COUNT(*) >= 3 retorna?
  1. Safety e Tools
  2. Tools
  3. Tools e First Aid
  4. Nenhuma linha
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

A equipe A tem os valores 20, 80 e 100; a equipe B tem 60 e 90. Depois de WHERE amount >= 60 GROUP BY team HAVING AVG(amount) > 80, o que permanece?
  1. B com média 75.
  2. A com média de aproximadamente 66,67.
  3. A com média 90.
  4. A com 90 e B com 75.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 3: Combinar valores ausentes, tipos e grupos10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

O que SELECT 17 / 5 retorna no SQLite?
  1. 3.4
  2. 4
  3. 0
  4. 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma consulta agrupa solicitações por equipe, mas seleciona um nome simples de funcionário. Cada equipe tem vários funcionários. O SQLite mostra um nome e o PostgreSQL rejeita a consulta. O que explica a diferença?
  1. O SQLite agrupa automaticamente por funcionário; o PostgreSQL exige um grupo explícito.
  2. O SQLite permite uma coluna não agrupada nem agregada; o nome não descreve a equipe inteira.
  3. O SQLite retorna o primeiro funcionário em ordem alfabética; o PostgreSQL exige ordenação explícita.
  4. O SQLite remove funcionários extras antes do agrupamento; o PostgreSQL mantém todos os funcionários.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

A unidade L tem os valores 30, 50 e 80; a unidade M tem 20 e 40. Você precisa do percentual de pedidos de pelo menos 60 em cada unidade, incluindo unidades sem nenhum pedido desse tipo. Quais percentuais devem aparecer?
  1. L 100,0%; M ausente.
  2. L 20,0%; M 0,0%.
  3. L 33,3%; M 0,0%.
  4. L 50,0%; M 0,0%.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

A cliente Inez tem os valores 20, 30 e 50; Omar tem 200. Quais são o valor médio por pedido e o valor total médio por cliente, nessa ordem?
  1. 75 e 150
  2. 150 e 75
  3. 75 e 100
  4. 100 e 150
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Uma tabela de estoque tem as linhas (department, quantity, price) (A, 2, 7), (A, 3, 4) e (B, 5, 9). O que SELECT SUM(quantity * price) FROM stock WHERE department = 'A' retorna?
  1. 55
  2. 71
  3. 26
  4. 14
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Uma coluna de região contém NULL, West, West, East e NULL. O que COUNT(DISTINCT region) retorna?
  1. 2
  2. 3
  3. 5
  4. 1
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Nenhuma linha em jobs corresponde a state = 'queued'. O que SELECT team, COALESCE(SUM(hours), 0) FROM jobs WHERE state = 'queued' GROUP BY team retorna?
  1. Uma linha com equipe NULL e total zero.
  2. Uma linha com equipe NULL e total NULL.
  3. Uma linha com total zero para cada equipe.
  4. Nenhuma linha.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Uma tabela tem os valores de área North, NULL, South, NULL e North. Depois de WHERE area IS NOT NULL GROUP BY area, quais são as contagens dos grupos?
  1. North 2; South 1; NULL 2.
  2. North 2; South 1.
  3. North 1; South 1.
  4. North 3; South 2.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Um relatório precisa dos valores médios de faturas por escritório, incluindo apenas faturas datadas de 2025 e exibindo apenas escritórios com mais de cinco faturas que atendam à condição. Onde devem ficar o teste de data e o teste de contagem?
  1. Ambos os testes em WHERE.
  2. Data em HAVING; contagem em WHERE.
  3. Ambos os testes em HAVING.
  4. Data em WHERE; contagem em HAVING.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Os pedidos têm os valores (data, valor) (2025-01-10, 90), (2026-01-12, 140), (2026-01-20, 60) e (2026-02-03, 110). Agrupe por ano e mês e por CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END. Quantos grupos resultam?
  1. 4
  2. 3
  3. 2
  4. 5
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 4: Analisar e concluir relatórios completos10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Um relatório agrupa uma tabela de reservas por sala. Qual condição HAVING mantém salas com pelo menos quatro reservas?
  1. HAVING COUNT(*) >= 4
  2. HAVING COUNT(*) > 4
  3. HAVING COUNT(*) = 4
  4. HAVING COUNT(*) <= 4
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

A filial A tem os valores 10, 40 e 70; a filial B tem 30 e 50. Compare o agrupamento após WHERE amount >= 30 com o agrupamento de todas as linhas usando HAVING MIN(amount) >= 30. Quais médias aparecem?
  1. WHERE: A 40 e B 40; HAVING: apenas B 40.
  2. WHERE: A 55 e B 40; HAVING: A 55 e B 40.
  3. WHERE: A 55 e B 40; HAVING: apenas B 40.
  4. WHERE: apenas B 40; HAVING: A 40 e B 40.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Um relatório sem agrupamento pode não ter linhas de entrada. Qual expressão fornece o percentual de linhas com um valor registrado, preserva as casas decimais e retorna NULL para uma população vazia tanto no SQLite quanto no PostgreSQL?
  1. 100 * COUNT(value) / NULLIF(COUNT(*), 0)
  2. 100.0 * COUNT(value) / NULLIF(COUNT(*), 0)
  3. 100.0 * COUNT(value) / COALESCE(COUNT(*), 1)
  4. 100.0 * COUNT(*) / NULLIF(COUNT(value), 0)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

No PostgreSQL, temperature é DOUBLE PRECISION. Como você arredonda sua média para duas casas decimais?
  1. ROUND(AVG(temperature), 2)
  2. CAST(ROUND(AVG(temperature)) AS NUMERIC)
  3. ROUND(CAST(AVG(temperature) AS INTEGER), 2)
  4. ROUND(CAST(AVG(temperature) AS NUMERIC), 2)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

No PostgreSQL, COUNT(*) FILTER (WHERE paid = 1) aparece ao lado de COUNT(*) em uma consulta agrupada sem cláusula WHERE. O que o filtro restringe?
  1. Todas as agregações do grupo.
  2. Apenas a exibição do resultado final.
  3. Apenas a agregação que conta pagamentos.
  4. Todas as linhas antes da formação dos grupos.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

O cliente U tem os valores 40 e 70, V tem 60, 60 e 10, e W tem 150. Quantos clientes têm pelo menos dois pedidos e um total acima de 120?
  1. 2
  2. 3
  3. 5
  4. 1
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Uma consulta mantém quatro linhas com os valores NULL, NULL, NULL e NULL. Quais são COUNT(*), COUNT(value) e MAX(value), nessa ordem?
  1. 4, 0, NULL
  2. 0, 0, NULL
  3. 4, 4, NULL
  4. 4, 0, 0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Uma tabela de visitas tem os pares (customer, zone) (Jo, East), (Jo, East), (Kai, West), (Kai, North), (Lee, NULL) e (Lee, NULL). Como adicionar zone ao agrupamento por customer altera a quantidade de grupos?
  1. Permanece em três.
  2. Aumenta de três para quatro.
  3. Aumenta de três para seis.
  4. Aumenta de três para cinco.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Um relatório agrupado inclui as zonas East, West e NULL. Um filtro de linha é WHERE zone <> 'West'. Quais grupos de zona podem permanecer?
  1. East e NULL.
  2. East e West.
  3. Apenas East.
  4. Apenas NULL.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Em uma tabela de pedidos do SQLite, maio de 2025 tem os valores 20 e 100, maio de 2026 tem 50 e 70, e junho de 2026 tem 200. Um relatório deve mostrar apenas meses de 2026 com pelo menos dois pedidos, com o valor médio arredondado. Qual resultado atende à solicitação?
  1. 2026-05: quatro pedidos, média 60,00.
  2. 2026-05: dois pedidos, média 60,00.
  3. 2026-06: um pedido, média 200,00.
  4. 2026-05: dois pedidos, média 120,00.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Travou em uma questão sua? Ajuda com Tarefas

Termos-Chave

58 Termos-Chave, cada um com sua definição

A

Agregação condicional
A agregação condicional faz a contribuição de cada linha depender de uma condição, permitindo várias medidas de subconjuntos em um relatório.
Um relatório regional pode exibir juntos todos os pedidos e os pedidos de valor alto sem filtrar primeiro os pedidos menores.
Agrupamento por várias colunas
O agrupamento por várias colunas forma um grupo para cada combinação de valores de agrupamento realmente presente nas linhas de entrada restantes.
Agrupar por região e cliente produz resultados separados de East para Ana e Dara, mantendo juntos os pedidos de Ana.
Apelido no SELECT
Um apelido no SELECT é um nome de resultado atribuído a uma expressão, que pode ser usado em ORDER BY e tem usos específicos de cada dialeto em outros pontos.
O PostgreSQL aceita ORDER BY total, mas exige que a expressão de agregação seja escrita por extenso em um HAVING do mesmo nível.
Arredondamento final
O arredondamento final reduz a precisão depois do cálculo completo da agregação, evitando alterações acumuladas ao arredondar cada entrada primeiro.
Três tarifas de 0,44 totalizam 1,32 antes do arredondamento para 1,3; arredondar cada tarifa primeiro produziria um total de 1,2.
AVG
AVG é uma função de agregação que calcula a média aritmética de suas entradas não NULL, usando cada valor registrado uma vez.
AVG(amount) resulta em 97,5 para oito pedidos cujos valores somam 780, medindo o valor médio por pedido.

C

CAST
CAST converte um valor para um tipo SQL solicitado, com efeitos que dependem do tipo de destino e do mecanismo de banco de dados.
Uma conversão para REAL no SQLite permite divisão decimal, enquanto uma conversão para NUMERIC pode manter um valor inteiro como inteiro.
Categoria definida por CASE
Uma categoria definida por CASE é um rótulo atribuído por condições em uma expressão CASE, que pode servir de base para um relatório agrupado.
Um limite de amount >= 100 coloca um pedido de exatamente 100 na categoria com o rótulo “large”.
Chave de ano e mês
Uma chave de ano e mês identifica um mês do calendário junto com seu ano, impedindo que o mesmo mês de anos diferentes seja reunido.
Os rótulos “2025-01” e “2026-01” produzem grupos separados em um relatório mensal que abrange os dois anos.
Cláusula FILTER de agregação
Uma cláusula FILTER de agregação restringe a entrada de uma função de agregação e deixa as outras funções da mesma consulta livres para usar outras linhas.
O PostgreSQL pode colocar uma contagem filtrada de pedidos de valor alto ao lado de uma contagem sem filtro de todos os pedidos do mesmo grupo.
COALESCE
COALESCE é uma função que retorna seu primeiro argumento não NULL, permitindo escolher um valor padrão para uma entrada ou um resultado final.
COALESCE(SUM(amount), 0) exibe zero quando uma entrada vazia produziria um total NULL.
Colação
Uma colação é um conjunto de regras que o banco de dados usa para comparar e ordenar textos, incluindo como maiúsculas e minúsculas afetam as comparações.
O menor valor entre textos pode mudar conforme a colação, mesmo que as linhas e a consulta MIN permaneçam iguais.
Coluna de agrupamento
Uma coluna de agrupamento fornece os valores que determinam quais linhas de entrada pertencem ao mesmo grupo em uma consulta de resumo agrupada.
Escolher cliente como coluna de agrupamento cria um relatório sobre clientes em vez de pedidos individuais.
Coluna não agrupada nem agregada
Uma coluna não agrupada nem agregada é uma coluna selecionada que não é coluna de agrupamento nem está dentro de uma função de agregação em uma consulta de agregação.
O SQLite pode mostrar um cliente ao lado do total de uma região mesmo quando vários clientes contribuíram para essa região.
Combinação distinta
Uma combinação distinta é um conjunto único de valores entre colunas selecionadas, tratado como uma linha em um resultado distinto.
East/Ana e East/Dara são pares separados quando um relatório lista combinações distintas de região e cliente.
Comparação sem arredondamento
Uma comparação sem arredondamento testa o valor calculado original, mesmo quando o resultado selecionado mostra uma versão arredondada dele.
Uma média exibida como 86,67 ainda pode não passar em HAVING AVG(amount) >= 86.67 se seu valor exato for menor.
Conciliação de contagens e totais
A conciliação de contagens e totais verifica se as contagens e os totais dos grupos somam as medidas equivalentes sem agrupamento sobre a mesma população filtrada.
Execute primeiro sem HAVING para que grupos excluídos não expliquem uma diferença entre o relatório e o total da entrada.
Condição de grupo
Uma condição de grupo testa uma propriedade de um grupo concluído, como se sua contagem ou média atende a um limite exigido.
Um mínimo de três pedidos por mês é uma condição de grupo porque precisa da contagem mensal concluída.
Condição de linha
Uma condição de linha pode ser avaliada para um registro de entrada, como verificar se sua data está em um intervalo ou se seu valor atende a um limite.
O teste amount >= 60 pode manter um pedido de East e remover outro, antes de existir qualquer resumo regional.
Conjunto de entrada com apenas valores NULL
Um conjunto de entrada com apenas valores NULL tem linhas, mas nenhum valor registrado para a expressão agregada, então COUNT(x) é zero.
Quatro pedidos com descontos desconhecidos resultam em COUNT(*) igual a quatro e COUNT(discount) igual a zero quando um filtro seleciona apenas esses pedidos.
Conjunto de entrada vazio
Um conjunto de entrada vazio é um conjunto sem linhas que entram em um cálculo, como quando uma condição WHERE não encontra registros correspondentes.
Uma contagem sem agrupamento de pedidos de South retorna zero quando todos os pedidos da tabela pertencem a outras regiões.
Contagem condicional
Uma contagem condicional conta apenas linhas que atendem a uma condição escolhida, frequentemente fazendo as linhas sem correspondência retornarem NULL dentro de COUNT.
COUNT(CASE WHEN amount >= 100 THEN 1 END) conta pedidos de valor alto e ignora os resultados NULL das linhas sem correspondência.
COUNT(*)
COUNT(*) é a forma de agregação que conta todas as linhas de entrada, incluindo linhas com valores ausentes em uma ou mais colunas.
Uma tabela com oito pedidos tem COUNT(*) igual a oito mesmo que um pedido não tenha região registrada.
COUNT(column)
COUNT(column) conta as linhas com valor não NULL na coluna indicada; inclui valores repetidos e zeros registrados.
COUNT(discount) inclui um pedido com desconto zero, mas deixa de fora um pedido com desconto NULL.
COUNT(DISTINCT column)
COUNT(DISTINCT column) conta os valores diferentes e não NULL de uma coluna, contando valores registrados repetidos apenas uma vez.
Use COUNT(DISTINCT customer) para obter a quantidade de clientes identificados, mesmo quando alguns fazem vários pedidos.
Critério de desempate
Um critério de desempate é uma chave de ordenação adicional que dá às linhas uma ordem repetível quando seus valores de ordenação anteriores são iguais.
ORDER BY total DESC, customer dá uma ordem estável a totais empatados de clientes antes de aplicar um limite.

D

Dependência funcional
Uma dependência funcional significa que um valor determina outro, como uma chave primária de pedido que determina o cliente desse pedido.
O PostgreSQL pode selecionar o cliente quando o agrupamento inclui a chave primária da tabela orders.
Detecção de duplicatas
A detecção de duplicatas encontra valores repetidos agrupando registros por esses valores e mantendo grupos com contagens acima de um.
Agrupar por cliente e usar HAVING COUNT(*) > 1 identifica clientes com registros repetidos de pedidos.
Diferença de arredondamento
Uma diferença de arredondamento é uma diferença causada pela redução de precisão, como quando partes arredondadas deixam de somar o todo arredondado.
Três partes percentuais iguais exibidas com uma casa decimal somam 99,9%, embora as partes exatas cubram 100%.
DISTINCT
DISTINCT remove valores ou linhas duplicados na etapa em que é aplicado, como dentro de uma função de agregação ou na lista de resultados.
SUM(DISTINCT quantity) soma cada valor de quantidade uma vez, então vendas reais repetidas podem ficar fora do total.
Divisão inteira
A divisão inteira divide operandos inteiros e descarta a parte fracionária no SQLite, PostgreSQL e SQL Server.
No SQLite, dividir 19 itens por oito pedidos com operandos inteiros resulta em 2 em vez da média 2,375.

E

Expressão de agregação
Uma expressão de agregação aplica uma função de resumo a uma coluna ou a um cálculo por linha, como somar a quantidade de cada linha multiplicada pelo preço.
SUM(amount - discount) avalia a subtração por linha antes de somar os resultados não NULL.
Expressão de agrupamento
Uma expressão de agrupamento calcula um valor de agrupamento a partir de cada linha, como um mês do calendário ou uma categoria atribuída por CASE.
Uma expressão de ano e mês combina pedidos de fevereiro e os mantém separados dos pedidos de fevereiro de outro ano.

F

Função de agregação
Uma função de agregação combina valores de várias linhas de entrada em um resultado, como uma contagem, uma soma, uma média ou um valor extremo.
Um relatório de vendas usa SUM(amount) para transformar vários valores de pedidos em um total para o período selecionado.

G

Granularidade
A granularidade de um relatório é o que uma linha do resultado representa, como um cliente ou mês, e determina o agrupamento necessário.
Um relatório com uma linha por cliente precisa de medidas no nível do cliente, mesmo quando a tabela de origem registra pedidos.
GROUP BY
GROUP BY é a cláusula que reúne linhas de entrada por valores compartilhados de colunas ou expressões, para que funções de agregação sejam executadas uma vez por grupo.
GROUP BY region permite que a mesma consulta calcule uma contagem de pedidos e um total de valores separados para cada região.
Grupo de valores NULL
Um grupo de valores NULL contém as linhas cujo valor de agrupamento está ausente; a SQL reúne essas linhas em um grupo de resultado.
Vários pedidos sem região compartilham um total que pode ser exibido com um rótulo como “Sem região”.

H

HAVING
HAVING é a cláusula que filtra grupos usando seus valores de agrupamento ou agregações calculadas depois que essas agregações existem.
HAVING SUM(amount) > 200 mantém regiões pelo total, sem remover pedidos menores dos grupos mantidos.

I

IS NULL
IS NULL é um teste SQL que é verdadeiro quando um valor está ausente, permitindo selecionar ou contar explicitamente registros ausentes.
WHERE region IS NULL seleciona pedidos cuja região não foi registrada, como o pedido de um cliente chamado Eli.

M

Média por cliente
Uma média por cliente dá uma contribuição ao total de cada cliente, o que difere de calcular a média de todos os valores de pedidos individuais.
Quando cinco clientes fazem oito pedidos que totalizam 780, a média por cliente é 156, embora a média dos oito pedidos seja 97,5.
Medida
Uma medida é a quantidade que um relatório calcula, como uma contagem, um total ou uma média, no nível de detalhe escolhido para o relatório.
Um relatório mensal de pedidos pode usar a contagem de pedidos e o valor médio como duas medidas da mesma população mensal.
MIN e MAX
MIN e MAX são funções de agregação que encontram o menor e o maior valor de entrada não NULL segundo as regras de comparação do banco de dados.
MIN(order_date) encontra a data mais antiga quando a coluna contém datas ou textos de data ISO com formato consistente.

N

NULL
NULL indica um valor SQL ausente ou desconhecido; operações aritméticas com ele produzem NULL, e ele é diferente de zero ou texto vazio.
Um desconto desconhecido pode fazer amount - discount ser NULL, levando SUM a ignorar o valor calculado dessa linha.
NULLIF
NULLIF retorna NULL quando seus dois argumentos são iguais e, caso contrário, retorna o primeiro argumento, sendo útil para divisores zero.
NULLIF(COUNT(*), 0) torna NULL o denominador de um relatório vazio, evitando um erro de divisão por zero no PostgreSQL.
NUMERIC e DECIMAL
NUMERIC e DECIMAL são tipos decimais exatos no PostgreSQL; no SQLite, esses nomes atribuem afinidade sem oferecer armazenamento decimal exato.
Para totais monetários exatos no SQLite, centavos armazenados como inteiros evitam depender de valores fracionários armazenados como aproximações binárias.
Número de ponto flutuante
Um número de ponto flutuante armazena uma aproximação binária de muitos valores decimais, então alguns cálculos podem mostrar pequenas imprecisões de arredondamento.
Uma adição DOUBLE PRECISION no PostgreSQL pode mostrar 0,30000000000000004 quando a aritmética decimal exata resulta em 0,3.

O

ONLY_FULL_GROUP_BY
ONLY_FULL_GROUP_BY é um modo do MySQL que rejeita expressões agrupadas com valores não agrupados que não são determinados pelo agrupamento.
O MySQL normalmente rejeita a seleção de um cliente arbitrário quando a consulta agrupa os pedidos apenas por região.
Operando decimal
Um operando decimal é uma entrada numérica que faz um cálculo preservar um resultado fracionário quando introduzida antes da divisão inteira.
Multiplicar a soma por 1,0 antes de dividir preserva a parte fracionária de uma média construída a partir de totais.
Ordem lógica de processamento da consulta
A ordem lógica de processamento da consulta descreve as etapas que definem o resultado de uma consulta, incluindo a filtragem de linhas antes dos cálculos de grupo.
Acompanhar WHERE antes de GROUP BY explica por que remover pedidos menores altera a média posterior de uma região.
ORDER BY
ORDER BY é a cláusula que solicita uma ordem definida para o resultado, incluindo a ordenação de linhas agrupadas por uma função de agregação ou seu apelido.
ORDER BY total DESC lista primeiro os maiores totais de grupos depois que cada grupo foi calculado.

P

Percentual dentro do grupo
Um percentual dentro do grupo mede um subconjunto como proporção de seu próprio grupo, usando a população completa desse grupo como denominador.
Um pedido de valor alto entre três pedidos de East corresponde a aproximadamente 33,3% dos pedidos de East, independentemente das contagens de outras regiões.

R

Regra de agrupamento
A regra de agrupamento exige que cada valor selecionado tenha um significado definido para seu grupo, por meio de agrupamento ou agregação.
Uma região com vários clientes não pode fornecer um único nome simples de cliente, a menos que a consulta especifique como escolhê-lo.
ROUND
ROUND é uma função que arredonda um valor numérico, com seu segundo argumento normalmente especificando as casas após a vírgula decimal.
ROUND(AVG(amount), 2) arredonda a média concluída para duas casas, mantendo intacto o cálculo anterior.

S

SUM
SUM é uma função de agregação que soma os valores numéricos não NULL de uma coluna ou expressão nas linhas de entrada.
SUM(quantity * unit_price) totaliza as receitas das linhas depois que cada quantidade é multiplicada pelo preço correspondente.

T

Tabela derivada
Uma tabela derivada é o resultado de uma consulta usado em FROM, permitindo que uma segunda consulta resuma linhas criadas pela primeira.
Uma consulta interna cria totais por cliente; uma consulta externa trata esses totais como entrada ao calcular sua média.
Total condicional
Um total condicional soma os valores das linhas correspondentes, normalmente com uma expressão CASE que retorna zero para as demais linhas.
Um total de pedidos de valor alto retorna o próprio valor que atende à condição a partir de CASE; retornar 1 contaria os pedidos.
Truncamento
O truncamento remove dígitos fracionários sem arredondar; o PostgreSQL oferece TRUNC, e o SQLite usa truncamento ao converter para inteiro.
TRUNC(2.97, 1) resulta em 2,9 no PostgreSQL, enquanto ROUND(2.97, 1) resulta em 3,0 para esse decimal exato.

V

Valor equidistante entre dois resultados de arredondamento
Um valor equidistante entre dois resultados de arredondamento está exatamente entre dois resultados possíveis; a escolha depende do tipo numérico e da regra de arredondamento.
O arredondamento exato de NUMERIC no PostgreSQL transforma 2,5 em 3 e -2,5 em -3, afastando ambos os valores intermediários de zero.

W

WHERE
WHERE é a cláusula que filtra linhas de entrada individuais antes do agrupamento, determinando quais registros contribuem para resumos posteriores.
Um relatório restrito a pedidos de 2026 usa uma condição de data em WHERE antes de calcular os totais mensais.

Sobre esta aula

Por StudeliRelatar um erro

Crie seus próprios Materiais de Estudo

Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.

Começar