postgis postgresql
David Sterling  

Beyond the Basics: 5 Powerful PostGIS Queries You Can Use Today

You’ve got PostGISqueries up and running—now what? If you completed the 15-minute quickstart, you’ve seen the basics: creating spatial tables, inserting points, and running simple distance queries. But PostGIS offers so much more.

In this follow-up guide, I’ll show you five immediately useful PostGIS techniques that go beyond simple point queries. These are practical patterns you can apply to real-world applications todayFor more information, check theofficial PostGIS documentation.https://postgis.net/documentation/

PostGIS Queries: Find Nearest Neighbors with KNN Indexing

The most common spatial question in real applications: “What are the 5 closest locations to me?” PostGIS has a special operator for this.

SELECT name,
ST_Distance(location, ST_Point(-122.4194, 37.7749)) as distance
FROM coffee_shops
ORDER BY location <-> ST_Point(-122.4194, 37.7749)
LIMIT 5;

The <-> operator uses KNN (K-Nearest Neighbor) indexing to find the closest points incredibly fast—even with millions of records. Unlike ST_DWithin which requires a distance threshold, this finds the N nearest regardless of how far they are.

PostGIS Queries: Create Buffer Zones Around Points

Need to find all locations within a service area? ST_Buffer creates a circular (or custom) zone around a point.

This creates a 500-meter radius around each point of interest and counts how many coffee shops fall within it. Perfect for delivery zones, service areas, or geofencing applications.

Check if a Point is Inside a Polygon

Testing whether a location falls within a boundary—like a delivery zone, neighborhood, or administrative region—is straightforward with ST_Contains.

— First, create a polygon representing a delivery zone
INSERT INTO delivery_zones (name, boundary) VALUES (
‘Downtown SF’,
ST_GeomFromText(‘POLYGON((
-122.42 37.77,
-122.40 37.77,
-122.40 37.79,
-122.42 37.79,
-122.42 37.77
))’, 4326)
);

— Then check which coffee shops are in that zone
SELECT shop.name
FROM coffee_shops shop
JOIN delivery_zones zone ON ST_Contains(zone.boundary, shop.location)
WHERE zone.name = ‘Downtown SF’;

This is essential for any location-based service that needs to respect boundaries: food delivery, ride-sharing zones, or regional restrictions.

Calculate Route Distances (Not Straight-Line)

ST_Distance gives you straight-line (“as the crow flies”) distance. For driving or walking distances, you’ll need to integrate with a routing engine. Here’s how to prepare your data for pgRouting, PostGIS’s routing extension.

— Create a simple road network
CREATE TABLE roads (
id SERIAL PRIMARY KEY,
name TEXT,
geom GEOMETRY(LINESTRING, 4326)
);

— After loading road data, create a topology
SELECT pgr_createTopology(‘roads’, 0.0001, ‘geom’, ‘id’);

— Find shortest path between two points
SELECT * FROM pgr_dijkstra(
‘SELECT id, source, target, ST_Length(geom) as cost FROM roads’,
start_node,
end_node,
directed := false
);

While pgRouting deserves its own deep dive, this gives you a starting point for calculating realistic travel distances rather than straight lines.

Cluster Points to Reduce Map Clutter

When you have thousands of markers on a map, clustering them improves performance and usability. PostGIS can pre-compute clusters at the database level.

SELECT
ST_NumGeometries(geom) as point_count,
ST_AsGeoJSON(ST_Centroid(geom)) as cluster_center
FROM (
SELECT
unnest(ST_ClusterWithin(location, 0.01)) as geom
FROM coffee_shops
) clusters
WHERE ST_NumGeometries(geom) > 1;

This groups points that are within 0.01 degrees of each other and returns the count and center point of each cluster. Perfect for creating those familiar map markers that say “5 locations in this area.”

Putting It All Together

These five patterns form the foundation of most spatial applications:

  1. KNN for “find nearest” features
  2. Buffers for service areas and geofencing
  3. Contains for boundary checks
  4. Routing for real-world distances
  5. Clustering for map performance

Each technique solves a common real-world problem. Start with the one that matches your use case, and you’ll have working spatial queries in minutes.

Next, consider exploring ST_Intersection for overlapping geometries, ST_Union for combining shapes, or diving deeper into pgRouting for advanced navigation features. PostGIS has a solution for nearly every spatial challenge you’ll encounter.If you’re new to spatial databases, check out our beginner’s guide to PostgreSQL and PostGIS queries.

SELECT
poi.name,
COUNT(shop.id) as shops_in_service_area
FROM points_of_interest poi
LEFT JOIN coffee_shops shop ON
ST_Intersects(
shop.location,
ST_Buffer(poi.location::geography, 500)::geometry
)
GROUP BY poi.id, poi.name;

Leave A Comment