Distância e Vizinhos Mais Próximos
Encontre o que está por perto.
Distância e Vizinhos Mais Próximos é uma aula grátis de SQL Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Academy inclui 4 aulas no total.
O que é distância espacial
Em bancos de dados geoespaciais, distância é a separação medida entre duas localizações geográficas. O PostGIS fornece funções avançadas para calcular distâncias entre pontos, linhas, polígonos e outros tipos de geometria.
Compreender as consultas de distância permite responder a perguntas como: Qual é o restaurante mais próximo de mim? ou Quais clientes estão a até 5 km do nosso armazém?
A função ST_Distance
ST_Distance(geom_a, geom_b) retorna a distância mínima entre dois objetos de geometria. Por padrão, ao usar tipos de geometria simples, o resultado é expresso nas mesmas unidades do sistema de referência de coordenadas, geralmente em graus para EPSG:4326.
Para obter resultados significativos em metros, você deve usar tipos geography ou reprojetar seus dados.
SELECT ST_Distance(
ST_MakePoint(28.9784, 41.0082)::geography,
ST_MakePoint(29.0100, 41.0200)::geography
) AS distance_meters;Configurando uma tabela de exemplo
Vamos criar uma tabela simples de locais com coordenadas geográficas. Usaremos o tipo geography para que todos os cálculos de distância retornem metros automaticamente — sem necessidade de projeção manual.
Essa tabela armazenará cafés de uma cidade, cada um com um nome e uma localização armazenada como um ponto.
CREATE TABLE cafes (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
location GEOGRAPHY(Point, 4326)
);
INSERT INTO cafes (name, location) VALUES
('Cafe Alpha', ST_MakePoint(28.9784, 41.0082)::geography),
('Cafe Beta', ST_MakePoint(28.9900, 41.0150)::geography),
('Cafe Gamma', ST_MakePoint(29.0100, 41.0200)::geography),
('Cafe Delta', ST_MakePoint(28.9650, 40.9980)::geography),
('Cafe Epsilon', ST_MakePoint(29.0250, 41.0350)::geography);Calculando a distância a partir de um ponto fixo
Depois de ter os dados de localização, você pode calcular a distância de cada linha até um ponto de referência. Aqui calculamos a distância de cada café até um usuário localizado nas coordenadas (28.9800, 41.0100).
O resultado é expresso em metros porque usamos o tipo geography.
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
ORDER BY distance_m;Encontrando o vizinho mais próximo
Para encontrar a única localização mais próxima de um determinado ponto, ordene pela distância e obtenha apenas uma linha com LIMIT 1. Esse é o padrão clássico de consulta de vizinho mais próximo.
Esse padrão é extremamente comum em aplicações com reconhecimento de localização: para encontrar a loja, o médico ou a parada de transporte público mais próximos.
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
LIMIT 1;O operador <-> para encontrar o vizinho mais próximo
O PostGIS fornece o operador <-> (KNN — K vizinhos mais próximos), que considera o índice. Diferentemente de ST_Distance em uma cláusula ORDER BY, <-> pode usar um índice espacial GiST para evitar a varredura de todas as linhas.
Prefira sempre <-> em ORDER BY quando precisar encontrar os vizinhos mais próximos com eficiência. Crie um índice como este para dar suporte ao operador:
CREATE INDEX ON cafes USING GIST (location);
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
LIMIT 5;Filtrando por distância (ST_DWithin)
ST_DWithin(geom_a, geom_b, distance) retorna TRUE quando duas geometrias estão dentro de uma distância especificada uma da outra. Para tipos geography, a distância é expressa em metros.
Isso é mais eficiente do que ST_Distance(...) < radius em uma cláusula WHERE, pois ST_DWithin considera o índice e interrompe a busca assim que a condição é atendida.
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
WHERE ST_DWithin(
location,
ST_MakePoint(28.9800, 41.0100)::geography,
2000
)
ORDER BY distance_m;As N localizações mais próximas com limite de raio
Um padrão comum em produção combina ST_DWithin como pré-filtro com a ordenação por <->. A verificação com ST_DWithin usa o índice espacial para descartar rapidamente as linhas distantes e, em seguida, os candidatos restantes são ordenados pela distância exata.
Isso permite obter com muita eficiência as N localizações mais próximas dentro de um raio máximo.
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m
FROM cafes
WHERE ST_DWithin(
location,
ST_MakePoint(28.9800, 41.0100)::geography,
5000
)
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
LIMIT 3;Distância entre duas tabelas (distância cruzada)
Você pode calcular distâncias entre linhas de duas tabelas diferentes usando uma junção com JOIN combinada com ST_Distance. Isso é útil para fazer correspondências, como associar cada cliente ao armazém mais próximo ou cada incidente ao hospital mais próximo.
A seguir, encontramos o café mais próximo para cada usuário em uma tabela users usando uma junção lateral — um padrão avançado do PostgreSQL para subconsultas por linha.
SELECT
u.username,
c.name AS nearest_cafe,
ROUND(ST_Distance(u.location, c.location)::NUMERIC) AS distance_m
FROM (
VALUES
('alice', ST_MakePoint(28.9810, 41.0095)::geography),
('bob', ST_MakePoint(29.0200, 41.0300)::geography)
) AS u(username, location)
CROSS JOIN LATERAL (
SELECT name, location
FROM cafes
ORDER BY location <-> u.location
LIMIT 1
) c;Formatando a saída da distância
Distâncias brutas em metros podem ser difíceis de ler. Você pode formatá-las como quilômetros ou adicionar rótulos fáceis de entender usando expressões CASE e formatação de texto. Esta consulta apresenta a distância em metros para distâncias curtas e em quilômetros para distâncias mais longas.
SELECT
name,
CASE
WHEN ST_Distance(location, ST_MakePoint(28.9800, 41.0100)::geography) < 1000
THEN ROUND(ST_Distance(location, ST_MakePoint(28.9800, 41.0100)::geography)::NUMERIC)
|| ' m'
ELSE ROUND((ST_Distance(location, ST_MakePoint(28.9800, 41.0100)::geography) / 1000.0)::NUMERIC, 2)
|| ' km'
END AS formatted_distance
FROM cafes
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography;Atribuindo uma classificação por distância
Funções de janela como RANK() e ROW_NUMBER() combinam perfeitamente com consultas de distância. Você pode atribuir uma classificação de proximidade a cada localização em relação a um usuário, o que é útil para criar listas de recomendações classificadas ou resultados de pesquisa ordenados por proximidade.
SELECT
name,
ROUND(
ST_Distance(
location,
ST_MakePoint(28.9800, 41.0100)::geography
)::NUMERIC
) AS distance_m,
ROW_NUMBER() OVER (
ORDER BY location <-> ST_MakePoint(28.9800, 41.0100)::geography
) AS proximity_rank
FROM cafes;Verificação de conhecimento
Verifique sua compreensão das consultas de distância e das pesquisas de vizinhos mais próximos no PostGIS.
Recapitulação da lição
Nesta lição, você aprendeu a trabalhar com distâncias espaciais e consultas de vizinhos mais próximos no PostGIS:
- ST_Distance calcula a distância exata entre duas geometrias; use o tipo geography para obter metros automaticamente.
- ST_DWithin filtra com eficiência as linhas dentro de um raio usando o índice espacial — prefira-o a
ST_Distance < radiusem cláusulas WHERE. - O operador <-> (KNN) em ORDER BY considera o índice e é a forma mais rápida de recuperar os N vizinhos mais próximos.
- Combine
ST_DWithincomo pré-filtro com a ordenação por<->para obter as consultas mais eficientes das N localizações mais próximas dentro de um raio. - CROSS JOIN LATERAL permite encontrar a correspondência mais próxima em outra tabela para cada linha.
- Funções de janela como
ROW_NUMBER()podem atribuir classificações de proximidade aos resultados ordenados por distância.
Esses padrões formam a base dos recursos que levam a localização em consideração em aplicações reais.
Perguntas Frequentes
A aula “Distância e Vizinhos Mais Próximos” é grátis?
Sim — o texto completo de “Distância e Vizinhos Mais Próximos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Academy, atualize para CoddyKit PRO. O curso de SQL Academy inclui 4 aulas no total.
O que vou aprender em “Distância e Vizinhos Mais Próximos”?
Encontre o que está por perto. Você pratica SQL Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar SQL Academy?
Nenhuma experiência prévia é necessária. SQL Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Distância e Vizinhos Mais Próximos”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de SQL Academy?
Sim. Cada aula de SQL Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Tipos de Dados Espaciais
- Distância e Vizinhos Mais Próximos
- Junções Espaciais e Contenção
- Índices Espaciais (GiST)