- Aprender
- Computação e TI
- Programação
- Noções básicas de SQL
- Agregação e agrupamento em SQL
Agregação e agrupamento em SQL
BásicoAula 4 de 6 do curso Curso de Noções básicas de SQL
O que você vai aprender
- 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áximosUse 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 distintosEscolha 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çõesSaiba 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.
- Encontrar totais, médias, valores mínimos e máximos
- 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 BYDivida 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 exibirSaiba 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 calculadosAgrupe 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.
- Resumir cada categoria com GROUP BY
- 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çãoEscreva condições HAVING sobre valores agregados, incluindo agregações que não são exibidas, para filtrar um resultado agrupado.
- Escolher entre WHERE e HAVINGUse 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.
- Manter os grupos que atendem a uma condição
- 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 percentuaisReconheç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çõesArredonde médias, totais e percentuais com ROUND, arredonde no momento certo e trate as diferenças entre SQLite e PostgreSQL.
- Evitar a divisão inteira em médias e percentuais
- 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 CASEColoque 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 perguntaTransforme 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.
- Contar e somar por condição com CASE
Guia de estudo de Agregação e agrupamento em SQL
1Resumir 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_id | customer | region | amount | quantity | discount | order_date |
|---|---|---|---|---|---|---|
| 1 | Ana | East | 120 | 2 | 10 | 2026-01-05 |
| 2 | Ben | West | 80 | 1 | NULL | 2026-01-17 |
| 3 | Ana | East | 45 | 3 | 5 | 2026-02-02 |
| 4 | Chen | North | 200 | 4 | NULL | 2026-02-14 |
| 5 | Ben | West | 60 | 1 | 0 | 2026-02-20 |
| 6 | Dara | East | 95 | 2 | NULL | 2026-03-03 |
| 7 | Chen | North | 150 | 5 | 15 | 2026-03-09 |
| 8 | Eli | NULL | 30 | 1 | NULL | 2026-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.
WHEREseleciona as linhas usadas pela função de agregação.- Calcule a contribuição de cada linha dentro de
SUMquando os valores precisarem permanecer associados. MINeMAXseguem 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ão | O 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.
COUNTretorna 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
COALESCEinterno altera os valores de entrada; um externo altera um resultado NULL. - Um conjunto de entrada vazio resulta em zero para
COUNTe 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.
2Agrupar 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 BYpara 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
HAVINGeORDER BYem 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 BYnão cria combinações ausentes com contagem zero.- A ordem das colunas de agrupamento não controla a ordem do resultado.
3Filtrar 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
HAVINGmantém ou remove grupos já calculados.- Uma função de agregação em
HAVINGnão precisa aparecer emSELECT. - Combine testes de grupo com
AND,OReNOT. - Repita expressões de agregação em
HAVINGpara 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:
FROMfornece as linhas.WHEREmantém as linhas que atendem à condição.GROUP BYforma grupos, e as funções de agregação calculam suas medidas.HAVINGmantém os grupos que atendem à condição.SELECTproduz os valores de saída;DISTINCTremove linhas duplicadas do resultado, se solicitado.ORDER BYordena o resultado, eLIMITmanté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ção | Cláusula |
|---|---|
Pedidos com amount >= 60 | WHERE |
| Pedidos em um determinado intervalo de datas | WHERE |
Regiões com SUM(amount) > 200 | HAVING |
| Clientes com mais de um pedido | HAVING 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
WHEREaltera as entradas das funções de agregação;HAVINGfiltra 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.
4Calcular 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 dados | Comportamento a observar |
|---|---|
| SQLite | A divisão inteira trunca; AVG retorna ponto flutuante. |
| PostgreSQL | A divisão inteira trunca; AVG de entradas inteiras ou NUMERIC retorna NUMERIC. |
| SQL Server | A 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
NULLIFpara tratar um denominador zero. - Os tipos de resultado das funções de agregação dependem do mecanismo e do tipo de entrada.
- A afinidade
NUMERICdo 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
NUMERICpara usarROUNDcom dois argumentos. - Casas de arredondamento negativas e conversões para inteiro diferem entre bancos de dados.
5Responder 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 0funciona 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
FILTERde agregação altera apenas as entradas dessa função de agregação. - Use
IS NULLpara 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?”
- As medidas são
COUNT(*)eAVG(amount). - A granularidade, ou o significado de uma linha do resultado, é um mês do calendário.
- A condição de linha mantém datas em 2026.
- A condição de grupo exige pelo menos três pedidos.
- 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
1Transformar linhas de pedidos em números de resumo confiáveis
13 passos
- 1Introduçã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.
- 2Explicaçã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 eMIN(amount)eMAX(amount)localizam os extremos. SemGROUP 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. - 3ExemploCalcule 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.
- 4ExemploEscolha 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.
- 5DesafioMantenha 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.
- 6Explicaçã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.
- 7ExemploConte a categoria ausente
A coluna de região tem oito linhas, mas apenas sete valores registrados.
COUNT(*)é oito,COUNT(region)é sete eCOUNT(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.
- 8DesafioEscolha a contagem certa
Uma coluna de cupons contém NULL, 0, 8, 8 e 0. Que valores
COUNT(*),COUNT(coupon)eCOUNT(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.
- 9Explicaçã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. - 10ExemploColoque 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.COALESCEao redor da soma concluída não pode recuperar as contribuições das linhas omitidas. - 11DesafioTrate um grupo sem valores conhecidos
Uma consulta mantém três linhas cujos valores são todos NULL. O que
COUNT(*),COUNT(amount)eSUM(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. - 12DesafioVerifique 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 eCOUNT(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. - 13Recapitulaçã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.
2Construir um relatório no nível certo de detalhe
14 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoDecida o que uma linha do resultado representa
- 2ExplicaçãoReúna linhas por região
- 3ExemploMantenha o grupo NULL visível
- 4DicaOrdene antes de manter as primeiras linhas
- 5DesafioPreveja quantos grupos restam
- 6ExplicaçãoExplique por que um nome é ambíguo
- 7ExemploCorrija o relatório a partir da pergunta
- 8DicaReconheça um resultado permissivo
- 9DesafioEscolha uma correção significativa
- 10ExemploDivida um grupo por um segundo valor
- 11ExplicaçãoCrie um rótulo de mês do calendário
- 12DesafioEncontre a expressão de agrupamento
- 13DesafioVerifique a granularidade e os rótulos do relatório
- 14RecapitulaçãoInterprete cada linha como um grupo
3Posicionar filtros antes ou depois da agregação
10 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoSepare população de seleção
- 2ExplicaçãoTeste o grupo concluído
- 3ExemploUse uma contagem sem exibi-la
- 4DesafioVerifique o valor efetivamente comparado
- 5ExplicaçãoAcompanhe as etapas lógicas do resultado
- 6ExemploRemova primeiro os pedidos menores
- 7ExemploDepois remova os totais menores de grupos
- 8DesafioIdentifique uma pergunta alterada
- 9DesafioCombine restrições de linha e de grupo
- 10RecapitulaçãoDeixe a condição indicar sua etapa
4Preservar frações e arredondar o resultado final
11 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoSepare cálculo de exibição
- 2ExemploEncontre onde a fração desaparece
- 3ExplicaçãoIntroduza o decimal cedo
- 4DicaTrate um denominador vazio
- 5DesafioCorrija uma expressão de percentual
- 6ExplicaçãoArredonde a média calculada
- 7ExemploVeja o arredondamento antecipado alterar um total
- 8DesafioVerifique uma diferença entre dialetos
- 9ConexãoEscolha o tipo para valores exatos
- 10DesafioVerifique o tipo antes de arredondar
- 11RecapitulaçãoAcompanhe o número em cada etapa
5Construir e verificar um resumo de negócios
13 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoMantenha juntos todos os pedidos e os pedidos selecionados
- 2ExplicaçãoFaça as linhas sem correspondência contribuírem com NULL
- 3ExemploMantenha o grupo inteiro disponível
- 4ExemploSome o valor ou some um
- 5DesafioPreserve o denominador de um subconjunto
- 6ExplicaçãoTransforme a pergunta de negócios
- 7ExemploConstrua o resultado mensal
- 8DicaVerifique antes de ocultar grupos
- 9ExplicaçãoAltere a unidade de entrada de uma média
- 10ExemploInterprete os dois níveis de consulta
- 11DesafioEscolha a unidade certa para a média
- 12DesafioConte apenas os grupos de clientes que atendem à condição
- 13RecapitulaçãoVerifique a população e a granularidade
Questões de Agregação e agrupamento em SQL
Conjunto 1: Interpretar contagens, grupos e cálculos10 Questões de Prática
Questão 1 de 10
SUM(distance) retorna?Mostrar respostaOcultar resposta
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
COUNT(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) retorna?Mostrar respostaOcultar resposta
Questão 3 de 10
AVG(delay) retorna?Mostrar respostaOcultar resposta
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
SELECT department, COUNT(*) FROM shifts GROUP BY department retorna?Mostrar respostaOcultar resposta
Questão 5 de 10
FROM parts GROUP BY category?Mostrar respostaOcultar resposta
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
paid_on com registros de 2024 a 2026. Qual expressão de agrupamento mantém cada mês do calendário separado?Mostrar respostaOcultar resposta
Questão 7 de 10
HAVING SUM(amount) > 200?Mostrar respostaOcultar resposta
>= 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
ORDER BY supplier. As categorias têm vários fornecedores. Como ela pode mostrar primeiro as categorias de maior custo sem alterar sua granularidade?Mostrar respostaOcultar resposta
Questão 9 de 10
SUM(quantity) / COUNT(*) * 1.0 retorna?Mostrar respostaOcultar resposta
1.0 * SUM(quantity) / COUNT(*).Questão 10 de 10
ROUND(SUM(fee), 1), mas mantém o grupo geral apenas com HAVING SUM(fee) >= 0.8. Qual resultado ela retorna?Mostrar respostaOcultar resposta
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
COUNT(priority) retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
MIN(delivery_date) e MAX(delivery_date) retornam, nessa ordem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
SELECT COUNT(*) FROM (SELECT DISTINCT city, agent FROM visits) AS pairs retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
SUM(cost - credit) e o custo líquido total pretendido, nessa ordem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
ORDER BY total DESC, customer ASC LIMIT 2 mantém, supondo que os nomes sejam ordenados alfabeticamente?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
ROUND(SUM(fee), 1) e SUM(ROUND(fee, 1)) produzem, nessa ordem, ignorando pequenas imprecisões de exibição de ponto flutuante?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
SELECT training FROM roster GROUP BY training HAVING COUNT(*) >= 3 retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
WHERE amount >= 60 GROUP BY team HAVING AVG(amount) > 80, o que permanece?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
SELECT 17 / 5 retorna no SQLite?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
SELECT SUM(quantity * price) FROM stock WHERE department = 'A' retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
COUNT(DISTINCT region) retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
jobs corresponde a state = 'queued'. O que SELECT team, COALESCE(SUM(hours), 0) FROM jobs WHERE state = 'queued' GROUP BY team retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
WHERE area IS NOT NULL GROUP BY area, quais são as contagens dos grupos?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END. Quantos grupos resultam?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
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
WHERE amount >= 30 com o agrupamento de todas as linhas usando HAVING MIN(amount) >= 30. Quais médias aparecem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
temperature é DOUBLE PRECISION. Como você arredonda sua média para duas casas decimais?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
COUNT(*) FILTER (WHERE paid = 1) aparece ao lado de COUNT(*) em uma consulta agrupada sem cláusula WHERE. O que o filtro restringe?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
COUNT(*), COUNT(value) e MAX(value), nessa ordem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
WHERE zone <> 'West'. Quais grupos de zona podem permanecer?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Agregação condicional
Agrupamento por várias colunas
Apelido no SELECT
ORDER BY e tem usos específicos de cada dialeto em outros pontos.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
AVG
AVG(amount) resulta em 97,5 para oito pedidos cujos valores somam 780, medindo o valor médio por pedido.C
CAST
REAL no SQLite permite divisão decimal, enquanto uma conversão para NUMERIC pode manter um valor inteiro como inteiro.Categoria definida por CASE
CASE, que pode servir de base para um relatório agrupado.amount >= 100 coloca um pedido de exatamente 100 na categoria com o rótulo “large”.Chave de ano e mês
Cláusula FILTER de agregação
COALESCE
COALESCE(SUM(amount), 0) exibe zero quando uma entrada vazia produziria um total NULL.Colação
MIN permaneçam iguais.Coluna de agrupamento
Coluna não agrupada nem agregada
Combinação distinta
Comparação sem arredondamento
HAVING AVG(amount) >= 86.67 se seu valor exato for menor.Conciliação de contagens e totais
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
Condição de linha
amount >= 60 pode manter um pedido de East e remover outro, antes de existir qualquer resumo regional.Conjunto de entrada com apenas valores NULL
COUNT(x) é zero.COUNT(*) igual a quatro e COUNT(discount) igual a zero quando um filtro seleciona apenas esses pedidos.Conjunto de entrada vazio
WHERE não encontra registros correspondentes.Contagem condicional
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(*) igual a oito mesmo que um pedido não tenha região registrada.COUNT(column)
COUNT(discount) inclui um pedido com desconto zero, mas deixa de fora um pedido com desconto NULL.COUNT(DISTINCT column)
COUNT(DISTINCT customer) para obter a quantidade de clientes identificados, mesmo quando alguns fazem vários pedidos.Critério de desempate
ORDER BY total DESC, customer dá uma ordem estável a totais empatados de clientes antes de aplicar um limite.D
Dependência funcional
Detecção de duplicatas
HAVING COUNT(*) > 1 identifica clientes com registros repetidos de pedidos.Diferença de arredondamento
DISTINCT
SUM(DISTINCT quantity) soma cada valor de quantidade uma vez, então vendas reais repetidas podem ficar fora do total.Divisão inteira
E
Expressão de agregação
SUM(amount - discount) avalia a subtração por linha antes de somar os resultados não NULL.Expressão de agrupamento
CASE.F
Função de agregação
SUM(amount) para transformar vários valores de pedidos em um total para o período selecionado.G
Granularidade
GROUP BY
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
H
HAVING
HAVING SUM(amount) > 200 mantém regiões pelo total, sem remover pedidos menores dos grupos mantidos.I
IS NULL
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
Medida
MIN e MAX
MIN(order_date) encontra a data mais antiga quando a coluna contém datas ou textos de data ISO com formato consistente.N
NULL
amount - discount ser NULL, levando SUM a ignorar o valor calculado dessa linha.NULLIF
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
Número de ponto flutuante
DOUBLE PRECISION no PostgreSQL pode mostrar 0,30000000000000004 quando a aritmética decimal exata resulta em 0,3.O
ONLY_FULL_GROUP_BY
Operando decimal
Ordem lógica de processamento da consulta
WHERE antes de GROUP BY explica por que remover pedidos menores altera a média posterior de uma região.ORDER BY
ORDER BY total DESC lista primeiro os maiores totais de grupos depois que cada grupo foi calculado.P
Percentual dentro do grupo
R
Regra de agrupamento
ROUND
ROUND(AVG(amount), 2) arredonda a média concluída para duas casas, mantendo intacto o cálculo anterior.S
SUM
SUM(quantity * unit_price) totaliza as receitas das linhas depois que cada quantidade é multiplicada pelo preço correspondente.T
Tabela derivada
FROM, permitindo que uma segunda consulta resuma linhas criadas pela primeira.Total condicional
CASE que retorna zero para as demais linhas.CASE; retornar 1 contaria os pedidos.Truncamento
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
NUMERIC no PostgreSQL transforma 2,5 em 3 e -2,5 em -3, afastando ambos os valores intermediários de zero.W
WHERE
WHERE antes de calcular os totais mensais.- 1Modelo relacional
- 2Consultas com SELECT
- 3Colunas calculadas e funções em SQL
- 4Agregação e agrupamento em SQL
- 5Junções SQL
- 6Criação de tabelas e alteração de dados
Sobre esta aula
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.