Pular para o conteúdo

A primeira escola especializada em tecnologia do Alto Solimões, com corpo técnico formado na área.

Modulo 2: CRUD Basico

Ordenando e Limitando

ORDER BY, LIMIT e OFFSET para organizar resultados

ORDER BY -- organizando os resultados

Sem ORDER BY, o banco de dados retorna os registros em qualquer ordem. Pode ate parecer que esta ordenado, mas nao ha garantia. Se a ordem importa (e quase sempre importa), use ORDER BY.

-- Ordenar por nome (A-Z) -- ASC e o padrao
SELECT * FROM usuarios ORDER BY nome;
SELECT * FROM usuarios ORDER BY nome ASC; -- mesmo resultado

-- Ordenar por idade (maior para menor)
SELECT * FROM usuarios ORDER BY idade DESC;

-- Produtos mais caros primeiro
SELECT * FROM produtos ORDER BY preco DESC;

Ordenando por multiplas colunas

Quando dois registros tem o mesmo valor na primeira coluna, o banco usa a segunda coluna para desempatar:

-- Ordenar por cidade (A-Z), e dentro de cada cidade, por nome (A-Z)
SELECT * FROM usuarios ORDER BY cidade ASC, nome ASC;

-- Produtos por categoria (A-Z), e dentro de cada categoria, mais caros primeiro
SELECT * FROM produtos ORDER BY categoria ASC, preco DESC;

-- Pedidos mais recentes primeiro, desempatando por valor
SELECT * FROM pedidos ORDER BY data_criacao DESC, valor_total DESC;

LIMIT -- limitando a quantidade

O LIMIT restringe quantos registros serao retornados:

-- Apenas os 10 primeiros usuarios
SELECT * FROM usuarios ORDER BY nome LIMIT 10;

-- Top 5 produtos mais caros
SELECT * FROM produtos ORDER BY preco DESC LIMIT 5;

-- O usuario mais novo
SELECT * FROM usuarios ORDER BY idade ASC LIMIT 1;

OFFSET -- pulando registros

O OFFSET pula uma quantidade de registros antes de comecar a retornar. Junto com LIMIT, ele permite paginacao:

-- Pula os 10 primeiros, retorna os proximos 10
SELECT * FROM usuarios ORDER BY nome LIMIT 10 OFFSET 10;

-- Pagina 1 (itens 1-10)
SELECT * FROM usuarios ORDER BY nome LIMIT 10 OFFSET 0;

-- Pagina 2 (itens 11-20)
SELECT * FROM usuarios ORDER BY nome LIMIT 10 OFFSET 10;

-- Pagina 3 (itens 21-30)
SELECT * FROM usuarios ORDER BY nome LIMIT 10 OFFSET 20;

Formula da paginacao

A formula e simples:

OFFSET = (pagina - 1) * itens_por_pagina
-- Pagina 1, 20 itens: OFFSET = (1-1) * 20 = 0
SELECT * FROM produtos ORDER BY id LIMIT 20 OFFSET 0;

-- Pagina 4, 20 itens: OFFSET = (4-1) * 20 = 60
SELECT * FROM produtos ORDER BY id LIMIT 20 OFFSET 60;

-- Pagina 10, 15 itens: OFFSET = (10-1) * 15 = 135
SELECT * FROM produtos ORDER BY id LIMIT 15 OFFSET 135;

No Prisma

// ORDER BY simples
const porNome = await prisma.usuario.findMany({
orderBy: { nome: 'asc' }
})

// ORDER BY multiplas colunas
const ordenado = await prisma.usuario.findMany({
orderBy: [
{ cidade: 'asc' },
{ nome: 'asc' }
]
})

// LIMIT
const top5 = await prisma.produto.findMany({
orderBy: { preco: 'desc' },
take: 5
})

// Paginacao completa
const pagina = 3
const itensPorPagina = 10

const usuarios = await prisma.usuario.findMany({
orderBy: { nome: 'asc' },
take: itensPorPagina,
skip: (pagina - 1) * itensPorPagina
})

// Contando o total para calcular paginas
const total = await prisma.usuario.count()
const totalPaginas = Math.ceil(total / itensPorPagina)

No Drizzle

import { asc, desc } from 'drizzle-orm'

// ORDER BY simples
const porNome = await db.select().from(usuarios).orderBy(asc(usuarios.nome))

// ORDER BY multiplas colunas
const ordenado = await db.select().from(usuarios)
.orderBy(asc(usuarios.cidade), asc(usuarios.nome))

// LIMIT
const top5 = await db.select().from(produtos)
.orderBy(desc(produtos.preco))
.limit(5)

// Paginacao completa
const pagina = 3
const itensPorPagina = 10

const resultado = await db.select().from(usuarios)
.orderBy(asc(usuarios.nome))
.limit(itensPorPagina)
.offset((pagina - 1) * itensPorPagina)

// Contando o total
import { count } from 'drizzle-orm'
const [{ total }] = await db.select({ total: count() }).from(usuarios)
const totalPaginas = Math.ceil(total / itensPorPagina)

No Lucid (AdonisJS)

// ORDER BY simples
const porNome = await Usuario.query().orderBy('nome', 'asc')

// ORDER BY multiplas colunas
const ordenado = await Usuario.query()
.orderBy('cidade', 'asc')
.orderBy('nome', 'asc')

// LIMIT
const top5 = await Produto.query().orderBy('preco', 'desc').limit(5)

// Paginacao completa (Lucid tem metodo paginate!)
const pagina = 3
const itensPorPagina = 10

const resultado = await Usuario.query()
.orderBy('nome', 'asc')
.paginate(pagina, itensPorPagina)

// resultado.total -- → total de registros
// resultado.perPage -- → itens por pagina
// resultado.currentPage -- → pagina atual
// resultado.lastPage -- → ultima pagina

// Paginacao manual com offset
const manual = await Usuario.query()
.orderBy('nome', 'asc')
.limit(itensPorPagina)
.offset((pagina - 1) * itensPorPagina)

Exercicios

  1. Escreva uma query que retorne os 3 produtos mais baratos de uma loja.
  2. Implemente paginacao: busque a pagina 5 com 15 itens por pagina, ordenando por data de cadastro (mais recente primeiro).
  3. Ordene usuarios por estado (A-Z) e, dentro de cada estado, por nome (A-Z). Retorne apenas os 20 primeiros.
  4. Usando Lucid, implemente um endpoint de listagem com paginacao usando o metodo paginate().
  5. Calcule quantas paginas existem se voce tem 247 registros e exibe 20 por pagina.

Referencias

Testa o que você leu

5 perguntas sobre esta aula. Errar aqui não custa nada - a explicação vem junto da correção.

Pergunta 1 de 5
Qual é a ordem padrão do `ORDER BY` quando não se escreve `ASC` nem `DESC`?