Junções Espaciais e Contenção
Quais pontos ficam em quais áreas.
Junções Espaciais e Contenção é uma aula grátis de SQL Academy no CoddyKit. Esta é a aula 3 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 é uma junção espacial
Uma junção espacial combina duas tabelas com base em uma relação geográfica, e não em uma chave correspondente. Em vez de perguntar "este ID é igual àquele ID?", você faz perguntas como "este ponto está dentro daquele polígono?" ou "estas duas formas se sobrepõem?"
O PostGIS amplia o PostgreSQL com tipos de geometria e funções espaciais que tornam essas junções possíveis. O resultado é igual ao de um JOIN SQL comum — linhas das duas tabelas combinadas — mas a condição é geométrica.
Configurando tabelas de exemplo
Vamos criar duas tabelas para trabalhar: cities, que armazenará localizações de pontos, e countries, que armazenará limites poligonais. Ambas usarão o tipo GEOMETRY do PostGIS com SRID 4326 (o padrão WGS84 de latitude/longitude).
O SRID (ID de referência espacial) informa ao PostGIS qual sistema de coordenadas deve ser usado. O SRID 4326 é o mais comum para dados de GPS.
CREATE TABLE countries (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
border GEOMETRY(POLYGON, 4326)
);
CREATE TABLE cities (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
location GEOMETRY(POINT, 4326)
);Inserindo dados de exemplo
Usaremos ST_GeomFromText para inserir valores de geometria no formato Well-Known Text (WKT). WKT é uma representação textual padrão para geometrias: POINT(lon lat) para pontos e POLYGON((...)) para polígonos.
Observe que a longitude vem antes da latitude em WKT — isso corresponde à convenção X, Y da matemática.
INSERT INTO countries (name, border) VALUES
('France', ST_GeomFromText('POLYGON((-5 42, 8 42, 8 51, -5 51, -5 42))', 4326)),
('Spain', ST_GeomFromText('POLYGON((-9 36, 3 36, 3 44, -9 44, -9 36))', 4326));
INSERT INTO cities (name, location) VALUES
('Paris', ST_GeomFromText('POINT(2.35 48.85)', 4326)),
('Madrid', ST_GeomFromText('POINT(-3.70 40.42)', 4326)),
('Bordeaux', ST_GeomFromText('POINT(-0.58 44.84)', 4326)),
('Lisbon', ST_GeomFromText('POINT(-9.14 38.72)', 4326));ST_Contains: a função principal
ST_Contains(geometry A, geometry B) retorna TRUE quando a geometria A contém completamente a geometria B. No nosso caso de uso, ST_Contains(country.border, city.location) retorna verdadeiro quando um ponto de cidade está dentro de um polígono de país.
Essa é a base das junções por contenção no PostGIS. A função faz parte do padrão OGC e funciona com qualquer combinação de tipos de geometria.
SELECT
ci.name AS city,
co.name AS country
FROM cities ci
JOIN countries co
ON ST_Contains(co.border, ci.location);ST_Within: a perspectiva inversa
ST_Within(geometry A, geometry B) é exatamente o oposto de ST_Contains: retorna TRUE quando a geometria A está inteiramente dentro da geometria B. ST_Within(city, country) é logicamente idêntico a ST_Contains(country, city).
Ambas as funções produzem o mesmo resultado neste caso. A escolha entre elas é uma questão de legibilidade — escolha a que soar mais natural na sua consulta.
-- These two queries return identical results:
-- Using ST_Contains (country contains city)
SELECT ci.name, co.name
FROM cities ci
JOIN countries co ON ST_Contains(co.border, ci.location);
-- Using ST_Within (city is within country)
SELECT ci.name, co.name
FROM cities ci
JOIN countries co ON ST_Within(ci.location, co.border);Usando LEFT JOIN para encontrar pontos sem correspondência
Um JOIN comum elimina as cidades que não ficam dentro de nenhum polígono de país. Use um LEFT JOIN combinado com uma verificação WHERE ... IS NULL para encontrar pontos que não têm nenhum polígono contendo-os — isso é útil para detectar problemas de qualidade dos dados ou pontos fora da sua área de cobertura.
SELECT
ci.name AS city,
co.name AS country
FROM cities ci
LEFT JOIN countries co
ON ST_Contains(co.border, ci.location)
ORDER BY co.name NULLS LAST;Contando pontos por polígono
As junções espaciais são especialmente úteis quando combinadas com agregação. Ao juntar cidades a países e depois agrupar por país, você pode contar quantos pontos ficam dentro de cada polígono. Esse padrão é extremamente comum em análises geográficas — contando lojas por região, eventos por distrito, sensores por zona e assim por diante.
SELECT
co.name AS country,
COUNT(ci.id) AS city_count
FROM countries co
LEFT JOIN cities ci
ON ST_Contains(co.border, ci.location)
GROUP BY co.name
ORDER BY city_count DESC;Usando um índice espacial para melhorar o desempenho
As junções espaciais podem ser lentas em conjuntos de dados grandes, pois cada ponto é testado contra cada polígono. Um índice GIST (árvore de pesquisa generalizada) permite que o PostGIS use um pré-filtro por caixa delimitadora para ignorar a maioria das comparações antes de executar o teste preciso de ST_Contains.
Sempre crie um índice GIST nas colunas de geometria usadas em junções ou filtros. O planejador de consultas o usará automaticamente.
-- Create GIST indexes on both geometry columns
CREATE INDEX idx_countries_border
ON countries USING GIST (border);
CREATE INDEX idx_cities_location
ON cities USING GIST (location);
-- The same join now benefits from index acceleration
SELECT ci.name, co.name
FROM cities ci
JOIN countries co
ON ST_Contains(co.border, ci.location);ST_Intersects: geometrias sobrepostas
ST_Intersects(A, B) retorna TRUE se duas geometrias compartilharem qualquer ponto — inclusive se apenas se tocarem em um limite. É mais permissiva que ST_Contains: dois polígonos sobrepostos se intersectam mesmo que nenhum contenha completamente o outro.
Para testes de ponto em polígono, ST_Intersects e ST_Contains são equivalentes, mas ST_Intersects usa o índice GIST com mais eficiência e costuma ser preferida na prática.
-- ST_Intersects is index-friendly and equivalent
-- to ST_Contains for point-in-polygon tests
SELECT
ci.name AS city,
co.name AS country
FROM cities ci
JOIN countries co
ON ST_Intersects(co.border, ci.location);Juntando pontos ao polígono mais próximo
Quando um ponto fica exatamente sobre um limite ou muito próximo de vários polígonos, talvez você queira o polígono mais próximo em vez de todas as correspondências. ST_Distance mede a distância entre duas geometrias, permitindo padrões com ORDER BY + LIMIT ou a junção especializada LATERAL com ORDER BY ... LIMIT 1.
Isso é chamado de junção pelo vizinho mais próximo e é comum ao ajustar trajetos de GPS a segmentos de vias ou atribuir um ponto à região mais próxima.
-- For each city, find the single closest country centroid
SELECT DISTINCT ON (ci.name)
ci.name AS city,
co.name AS nearest_country,
ST_Distance(ci.location, ST_Centroid(co.border)) AS dist
FROM cities ci
CROSS JOIN countries co
ORDER BY ci.name, dist;Exemplo prático: restaurantes em distritos
Aqui está um exemplo realista de ponta a ponta: descobrir a qual distrito da cidade cada restaurante pertence e depois contar os restaurantes por distrito. Esse padrão se aplica a qualquer cenário de ponto em polígono — caixas eletrônicos em bairros, acidentes em zonas policiais, pedidos em zonas de entrega.
A consulta usa ST_Within em uma junção espacial e agrupa os resultados para gerar um relatório resumido.
-- Assume tables: districts(id, name, boundary GEOMETRY)
-- restaurants(id, name, location GEOMETRY)
SELECT
d.name AS district,
COUNT(r.id) AS restaurant_count,
STRING_AGG(r.name, ', ' ORDER BY r.name) AS names
FROM districts d
LEFT JOIN restaurants r
ON ST_Within(r.location, d.boundary)
GROUP BY d.name
ORDER BY restaurant_count DESC;Verificação rápida
Teste sua compreensão sobre junções espaciais e contenção no PostGIS.
Recapitulação: junções espaciais e contenção
Nesta lição, você aprendeu a responder à pergunta "quais pontos ficam em quais áreas?" usando junções espaciais do PostGIS.
Principais conclusões:
- ST_Contains(polygon, point) — retorna verdadeiro quando o polígono contém completamente o ponto.
- ST_Within(point, polygon) — o inverso; é logicamente equivalente a ST_Contains.
- ST_Intersects — teste de sobreposição mais geral; favorece o uso do índice em consultas de ponto em polígono.
- Índices GIST nas colunas de geometria são essenciais para o desempenho em grande escala.
- Combine junções espaciais com GROUP BY para contar ou agregar pontos por região.
- Use LEFT JOIN para detectar pontos que ficam fora de todos os polígonos.
As junções espaciais permitem realizar análises geográficas diretamente em SQL — sem necessidade de uma ferramenta GIS externa.
Perguntas Frequentes
A aula “Junções Espaciais e Contenção” é grátis?
Sim — o texto completo de “Junções Espaciais e Contenção” é 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 “Junções Espaciais e Contenção”?
Quais pontos ficam em quais áreas. 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 3 de 4.
Quanto tempo leva a aula “Junções Espaciais e Contenção”?
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)