Ordenando e Limitando
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
- Escreva uma query que retorne os 3 produtos mais baratos de uma loja.
- Implemente paginacao: busque a pagina 5 com 15 itens por pagina, ordenando por data de cadastro (mais recente primeiro).
- Ordene usuarios por estado (A-Z) e, dentro de cada estado, por nome (A-Z). Retorne apenas os 20 primeiros.
- Usando Lucid, implemente um endpoint de listagem com paginacao usando o metodo
paginate(). - 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.