Geo Functions¶
SemQL has two built-in geo functions for working with coordinates: GEO_DISTANCE() and GEO_WITHIN_RADIUS(). Both take latitude/longitude pairs and return results you can use directly in your queries.
These functions are database-agnostic — they work regardless of which database you're connected to (Snowflake, BigQuery, Redshift, etc.), because SemQL compiles them to standard trigonometry (the Haversine formula) that runs on any SQL engine.
GEO_DISTANCE¶
Returns the distance in kilometers between two geographic coordinates.
Syntax¶
GEO_DISTANCE(lat1, lng1, lat2, lng2)
| Parameter | Type | Description |
|---|---|---|
lat1 | number | Latitude of the first point |
lng1 | number | Longitude of the first point |
lat2 | number | Latitude of the second point |
lng2 | number | Longitude of the second point |
Examples¶
Distance from a fixed point to a column value:
SELECT
store_name,
city,
GEO_DISTANCE(48.8566, 2.3522, store_lat, store_lng) AS distance_from_paris_km
FROM retail_stores
ORDER BY distance_from_paris_km ASC
Filter by a calculated distance:
SELECT
store_name,
GEO_DISTANCE(51.5074, -0.1278, store_lat, store_lng) AS distance_km
FROM retail_stores
WHERE GEO_DISTANCE(51.5074, -0.1278, store_lat, store_lng) <= 50
ORDER BY distance_km
Distance between two columns (e.g., customer location to nearest warehouse):
SELECT
order_id,
customer_name,
GEO_DISTANCE(customer_lat, customer_lng, warehouse_lat, warehouse_lng) AS delivery_distance_km
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id
JOIN warehouses ON orders.warehouse_id = warehouses.warehouse_id
ORDER BY delivery_distance_km DESC
LIMIT 20
GEO_WITHIN_RADIUS¶
Returns true if a point is within a given radius of another point, false otherwise. Useful for filtering by proximity.
Syntax¶
GEO_WITHIN_RADIUS(lat1, lng1, lat2, lng2, radius_km)
| Parameter | Type | Description |
|---|---|---|
lat1 | number | Latitude of the reference point |
lng1 | number | Longitude of the reference point |
lat2 | number | Latitude of the point to test |
lng2 | number | Longitude of the point to test |
radius_km | number | Radius in kilometers |
Examples¶
Filter stores within 25 km of a city:
SELECT store_name, city, store_lat, store_lng
FROM retail_stores
WHERE GEO_WITHIN_RADIUS(52.3676, 4.9041, store_lat, store_lng, 25)
ORDER BY store_name
Categorize records by proximity:
SELECT
customer_name,
city,
CASE
WHEN GEO_WITHIN_RADIUS(48.8566, 2.3522, customer_lat, customer_lng, 50)
THEN 'Within 50km of Paris'
WHEN GEO_WITHIN_RADIUS(48.8566, 2.3522, customer_lat, customer_lng, 200)
THEN 'Within 200km of Paris'
ELSE 'Outside 200km'
END AS proximity_band
FROM customers
ORDER BY proximity_band
Count customers within a radius:
SELECT
COUNT(*) AS customer_count
FROM customers
WHERE GEO_WITHIN_RADIUS(40.7128, -74.0060, customer_lat, customer_lng, 100)
Combining both functions¶
A common pattern is to show the actual distance alongside a proximity flag:
SELECT
store_name,
city,
GEO_DISTANCE(50.8503, 4.3517, store_lat, store_lng) AS distance_from_brussels_km,
GEO_WITHIN_RADIUS(50.8503, 4.3517, store_lat, store_lng, 100) AS within_100km
FROM retail_stores
ORDER BY distance_from_brussels_km
Notes¶
- Coordinates must be numeric (decimal degrees). Null coordinates will cause an error.
- Distances are always in kilometers.
- The Haversine formula assumes a spherical Earth — it's accurate to within ~0.5% for most practical distances.
- Both functions are compiled to standard SQL math functions (
SIN,COS,ACOS,RADIANS) and work on all supported database dialects.