0Pricing
SQL Academy · Aula

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 &lt;-&gt; 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 < radius em 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_DWithin como 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

  1. Tipos de Dados Espaciais
  2. Distância e Vizinhos Mais Próximos
  3. Junções Espaciais e Contenção
  4. Índices Espaciais (GiST)
← Voltar para SQL Academy