sqlpostgresqlmysqlclickhouse

CEIL e CEILING no SQL: arredondar para cima ao inteiro

Como CEIL/CEILING arredonda para cima, calcula paginas de paginacao e cria buckets, e como difere de FLOOR e ROUND.

2 min de leituraReferencesql · postgresql · mysql · clickhouse · math · pagination

CEIL (tambem escrito CEILING) arredonda um numero para cima ate o inteiro mais proximo que nao seja menor que o valor de entrada. E a ferramenta basica para contar paginas de paginacao, agrupar dados em buckets e qualquer logica do tipo "quantos recipientes preciso para guardar N itens".

Comportamento basico

CEIL sempre avanca em direcao ao infinito positivo. Inteiros ficam como estao; qualquer parte fracionaria puxa o resultado para cima.

SELECT
  CEIL(4.1)  AS a,   -- 5
  CEIL(4.0)  AS b,   -- 4
  CEIL(-4.1) AS c,   -- -4  (toward zero, not away)
  CEILING(7.0001) AS d; -- 8

Pontos principais:

  • CEIL e CEILING sao sinonimos exatos em todos os bancos de dados importantes.
  • Para numeros negativos, "para cima" significa em direcao ao zero: CEIL(-4.1) e -4, nao -5.
  • No PostgreSQL o resultado sobre numeric continua numeric, e sobre double precision continua double precision. A parte fracionaria e sempre descartada.

Contar paginas de paginacao

O caso classico: voce tem total linhas e per_page por pagina, entao quantas paginas existem? A divisao inteira trunca o resto, por isso voce precisa de CEIL.

SELECT
  COUNT(*) AS total_orders,
  CEIL(COUNT(*)::numeric / 25) AS total_pages
FROM orders
WHERE status = 'paid';

O mesmo truque por pais, para saber quantas telas de lista sao necessarias para mostrar todos os usuarios a 20 por pagina:

SELECT
  country,
  COUNT(*) AS users,
  CEIL(COUNT(*)::numeric / 20) AS pages
FROM users
GROUP BY country
ORDER BY users DESC;

Pegadinha: a divisao inteira. No PostgreSQL 5 / 2 e 2 (inteiro), e CEIL(5 / 2) retorna 2, nao 3. A divisao ja aconteceu antes de o CEIL rodar. Sempre converta pelo menos um operando para um tipo fracionario: CEIL(5::numeric / 2) ou CEIL(5.0 / 2).

Buckets e agrupamento por faixas

CEIL e otimo para mapear valores continuos em buckets discretos de largura fixa. Agrupe funcionarios em faixas salariais de largura 10000:

SELECT
  CEIL(salary / 10000.0) * 10000 AS salary_band,
  COUNT(*) AS people
FROM employees
GROUP BY CEIL(salary / 10000.0)
ORDER BY salary_band;

Um funcionario que ganha 41000 cai na faixa 50000 (a borda superior do intervalo de 40001 a 50000). Se voce quer a borda inferior, use FLOOR. Voce pode fatiar os valores dos pedidos em segmentos de preco da mesma forma:

SELECT
  CEIL(amount / 100.0) AS price_bucket,
  COUNT(*) AS orders
FROM orders
GROUP BY CEIL(amount / 100.0)
ORDER BY price_bucket;

CEIL versus FLOOR e ROUND

Tres funcoes, tres direcoes diferentes:

  • CEIL(x) arredonda para cima, ao infinito positivo: CEIL(2.1) = 3, CEIL(2.9) = 3.
  • FLOOR(x) arredonda para baixo, ao infinito negativo: FLOOR(2.9) = 2, FLOOR(-2.1) = -3.
  • ROUND(x) arredonda ao inteiro mais proximo: ROUND(2.4) = 2, ROUND(2.5) = 3.
SELECT
  x,
  CEIL(x)  AS up,
  FLOOR(x) AS down,
  ROUND(x) AS nearest
FROM (VALUES (2.1), (2.5), (2.9), (-2.5)) AS t(x);

Para paginacao e calculos de "quantos recipientes", use apenas CEIL: ate uma unica linha extra precisa de outra pagina inteira, e ROUND erraria exatamente no ponto medio.

Diferencas entre bancos de dados

  • PostgreSQL e MySQL: CEIL e CEILING se comportam igual; no MySQL tambem cuidado com a divisao inteira, use / com literais fracionarios ou um cast.
  • ClickHouse: a funcao e ceil e aceita um segundo argumento de precisao: ceil(4.123, 1) e 4.2. Isso e util para arredondar para cima ate decimos ou centesimos, algo que o CEIL padrao nao consegue.
  • Em todos os sistemas CEIL(NULL) retorna NULL, entao leve isso em conta em agregacoes e COALESCE.
-- ClickHouse: round up to one decimal place
SELECT ceil(4.123, 1) AS r;  -- 4.2

Pratique com exercícios reais

Resolva exercícios no treinador de SQL com correção instantânea e dicas.

Abrir o treinador