Calculate the distance between two latitude/longitude coordinates in SQL Server
Context

Calculating the distance between two places can be quite tricky, there are some good articles out there, however this page will only go into the code.
For more information on how it distances are calculated on a sphere, have a look at Haversine Formula on Wikipedia, it's a bit complex, hence us not wanting to duplicate the content.
We found some of this code online and have adapted it to an SQL Function, with the ability to ask for miles or kilometres.
This only calculates "as the crow flies", however it was tested as part of an app we'd built on an IPhone and the distances were spot on.
We've also included an example for English football team distances at the bottom.
SQL Server
CREATE FUNCTION CoordinateDistanceMiles(@Latitude1 float,@Longitude1 float,@Latitude2 float,@Longitude2 float,@Distance NVARCHAR(10))RETURNS FLOATAS BEGIN-- CONSTANTSDECLARE @EarthRadiusInMiles FLOAT=(CASE @Distance WHEN 'Miles' THEN 3959 WHEN 'Kilometers' THEN 6371 ELSE 0 END);DECLARE @PI FLOAT=PI();DECLARE @lat1Radians FLOAT=@Latitude1 * @PI / 180DECLARE @long1Radians FLOAT=@Longitude1 * @PI / 180;DECLARE @lat2Radians FLOAT=@Latitude2 * @PI / 180;DECLARE @long2Radians FLOAT=@Longitude2 * @PI / 180;RETURN Acos(Cos(@lat1Radians)*Cos(@long1Radians)*Cos(@lat2Radians)*Cos(@long2Radians)+Cos(@lat1Radians)*Sin(@long1Radians)*Cos(@lat2Radians)*Sin(@long2Radians)+Sin(@lat1Radians)*Sin(@lat2Radians)) * @EarthRadiusInMiles;END
Practical Example
It's always easier to visualise data with an example we can comprehend, so I've taken all of the English league football clubs for 2022-2023, and sourced their ground locations (if they haven't moved in a couple of seasons).
What we will do is then use this data to work out how far each club has to travel (as the crow flies).
Create Data Set
CREATE TABLE Club(ClubName NVARCHAR(100),ClubStadium NVARCHAR(100),ClubLeague NVARCHAR(100),ClubLon float,ClubLat float)GO--Season 22/23INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Arsenal','Emirates Stadium','EPL',-0.108436,51.554901INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Aston Villa','Villa Park','EPL',-1.88508,52.509201INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Bournemouth','Seward Stadium','EPL',-1.83839,50.735199INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Brentford','Griffin Park','EPL',-0.302621,51.488201INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Brighton and Hove Albion','Amex Stadium','EPL',-0.08014,50.860901INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Chelsea','Stamford Bridge','EPL',-0.191034,51.481602INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Crystal Palace','Selhurst Park','EPL',-0.085455,51.3983INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Everton','Goodison Park','EPL',-2.96619,53.438702INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Fulham','Craven Cottage','EPL',-0.221619,51.474899INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Leeds United','Elland Road','EPL',-1.57212,53.7775INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Leicester City','King Power Stadium','EPL',-1.14217,52.6203INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Liverpool','Anfield','EPL',-2.96096,53.430801INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Manchester City','Etihad Stadium','EPL',-2.20024,53.483002INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Manchester United','Old Trafford','EPL',-2.29139,53.4631INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Newcastle United','St James Park','EPL',-1.62179,54.975601INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Nottingham Forest','The City Ground','EPL',-1.13258,52.939899INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Southampton','St Mary''s Stadium','EPL',-1.39114,50.9058INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Tottenham Hotspur','Tottenham Hotspur Stadium','EPL',-0.066389,51.604401INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'West Ham','London Stadium','EPL',-0.016587,51.5383INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Wolverhampton Wanderers','Molineux','EPL',-2.13061,52.590401INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Birmingham City','St Andrews','CHP',-1.86824,52.475601INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Blackburn Rovers','Ewood Park','CHP',-2.48937,53.7286INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Blackpool','Bloomfield Road','CHP',-3.04834,53.8046INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Bristol City','Ashton Gate','CHP',-2.62021,51.439999INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Cardiff City','Cardiff City Stadium','CHP',-3.20413,51.4729INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Coventry City','Ricoh Arena','CHP',-1.49563,52.448101INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Huddersfield Town','The Galpharm Stadium','CHP',-1.76837,53.654301INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Hull City','KC Stadium','CHP',-0.368009,53.746498INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Luton Town','Kenilworth Road','CHP',-0.43155,51.884201INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Middlesbrough','Riverside','CHP',-1.21776,54.578098INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Millwall','The Den','CHP',-0.050743,51.485901INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Norwich City','Carrow Road','CHP',1.30912,52.622101INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Preston North End','Deepdale','CHP',-2.68832,53.771999INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Queens Park Rangers','Loftus Road','CHP',-0.232204,51.5093INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Reading','Madjeski Stadium','CHP',-0.982777,51.422199INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Rotherham United','New York Stadium','CHP',-1.36172,53.428101INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Sheffield United','Bramall Lane','CHP',-1.47083,53.3703INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Stoke City','Britannia Stadium','CHP',-2.17542,52.9884INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Sunderland','Stadium of Light','CHP',-1.38837,54.9146INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Swansea City','Liberty Stadium','CHP',-3.93473,51.642799INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Watford','Vicarage Road','CHP',-0.401569,51.649799INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'West Bromwich Albion','The Hawthorns','CHP',-1.96418,52.508999INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Wigan Athletic','DW Stadium','CHP',-2.65415,53.547699INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Burnley','Turf Moor','CHP',-2.23018,53.788799INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Accrington Stanley','Crown Ground','L1',-2.37106,53.7654INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Barnsley','Oakwell','L1',-1.46756,53.552399INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Bolton Wanderers','University of Bolton Stadium','L1',-2.53571,53.580502INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Bristol Rovers','Memorial Stadium','L1',-2.58315,51.486198INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Burton Albion','Pirelli Stadium','L1',-1.62708,52.821899INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Cambridge United','Abbey Stadium','L1',0.154298,52.212799INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Charlton Athletic','The Valley','L1',0.036757,51.4865INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Cheltenham Town','Whaddon Road','L1',-2.06021,51.9062INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Derby County','Pride Park','L1',-1.44727,52.914902INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Exeter City','St James Park, Exeter','L1',-3.52109,50.730701INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Fleetwood Town','Highbury Stadium','L1',-3.02484,53.9165INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Ipswich Town','Portman Road','L1',1.14554,52.054401INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'MK Dons','Stadiummk','L1',-0.733507,52.009602INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Morecambe','Globe Arena','L1',-2.84707,54.067501INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Oxford United','Kassam Stadium','L1',-1.20775,51.7164INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Peterborough United','London Road','L1',-0.240434,52.5648INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Plymouth Argyle','Home Park','L1',-4.15076,50.388199INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Port Vale','Vale Park','L1',-2.1926,53.049999INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Portsmouth','Fratton Park','L1',-1.06389,50.796398INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Sheffield Wednesday','Hillsborough','L1',-1.50075,53.411499INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Shrewsbury Town','New Meadow','L1',-2.74931,52.688599INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Wycombe Wanderers','Adams Park','L1',-0.800299,51.6306INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Lincoln City FC','Sincil Bank','L1',-0.540811,53.218289INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Forrest Green Rovers','The New Lawn','L1',-2.237892,51.698975INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'AFC Wimbledon','Plough Lane','L2',-0.186736,51.4314INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Bradford City','Valley Parade','L2',-1.75902,53.804199INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Carlisle United','Brunton Park','L2',-2.91365,54.8955INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Colchester United','Weston Homes Community Stadium','L2',0.897861,51.923401INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Crawley Town','Broadfield Stadium','L2',-0.194579,51.099602INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Crewe Alexandra','Alexandra Stadium','L2',-2.43569,53.087502INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Doncaster Rovers','Keepmoat Stadium','L2',-1.11382,53.509899INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Gillingham','Priestfield Stadium','L2',0.560367,51.384399INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Hartlepool United','Victoria Park','L2',-1.21274,54.689098INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Leyton Orient','Brisbane Road','L2',-0.012551,51.560101INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Mansfield Town','Field Mill','L2',-1.2013,53.137798INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Newport County','Rodney Parade','L2',-2.98902,51.588902INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Northampton Town','Sixfields Stadium','L2',-0.933485,52.235199INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Rochdale','Spotland Stadium','L2',-2.17993,53.620899INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Stevenage Borough','The Lamex Stadium','L2',-0.193664,51.889801INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Swindon Town','The County Ground','L2',-1.77107,51.564499INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Tranmere Rovers','Prenton Park','L2',-3.03269,53.373798INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Walsall','Bescot Stadium','L2',-1.99053,52.565498INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Stockport County','Edgeley Park','L2',-2.166389,53.399722INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Salford City','The Peninsula Stadium','L2',-2.276775,53.513631INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Barrow','Holker Street','L2',-3.235,54.123333INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Grimsby Town','Blundell Park','L2',-0.046497,53.570225INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Sutton Utd','Gander Green Lane','L2',-0.204444,51.3675INSERT INTO Club(ClubName,ClubStadium,ClubLeague,ClubLon,ClubLat) SELECT 'Harrogate Town','Wetherby Road','L2',-1.514444,53.991667
Get the data
To compare all of the data, we will need to use a full outer join where the clubs are in the same league, but not the same team as being tested.
There are two examples below, one with all of the data, the second ordered by distance.
SQL Statement
SELECT *,dbo.CoordinateDistanceMiles(Home.ClubLat,Home.ClubLon,Away.ClubLat,Away.ClubLon,'Miles') DistanceFROM Club HomeFULL OUTER JOIN Club Away ON Away.ClubLeague=Home.ClubLeague AND Away.ClubName<>Home.ClubNameGOSELECT Home.ClubName,Home.ClubLeague,SUM(dbo.CoordinateDistanceMiles(Home.ClubLat,Home.ClubLon,Away.ClubLat,Away.ClubLon,'Miles')) DistanceFROM Club HomeFULL OUTER JOIN Club Away ON Away.ClubLeague=Home.ClubLeague AND Away.ClubName<>Home.ClubNameGROUP BY Home.ClubName,Home.ClubLeagueORDER BY Distance DESCGO
Results
ClubName | ClubLeague | Distance |
Plymouth Argyle | L1 | 4453.891898 |
Carlisle United | L2 | 3920.227433 |
Newcastle United | EPL | 3776.541427 |
Exeter City | L1 | 3715.99945 |
Sunderland | CHP | 3644.164045 |
Swansea City | CHP | 3475.832002 |
Norwich City | CHP | 3442.73664 |
Hartlepool United | L2 | 3412.083145 |
Ipswich Town | L1 | 3286.248793 |
Gillingham | L2 | 3256.55143 |
Crawley Town | L2 | 3255.519895 |
Newport County | L2 | 3246.542226 |
Morecambe | L1 | 3214.327594 |
Middlesbrough | CHP | 3195.794382 |
Cardiff City | CHP | 3194.984001 |
Barrow | L2 | 3169.301103 |
Portsmouth | L1 | 3164.602876 |
Colchester United | L2 | 3108.978503 |
Fleetwood Town | L1 | 3107.92468 |
Millwall | CHP | 3068.132637 |
Bristol City | CHP | 2993.14002 |
Queens Park Rangers | CHP | 2953.272006 |
Sutton Utd | L2 | 2919.397634 |
AFC Wimbledon | L2 | 2857.466638 |
Reading | CHP | 2851.657641 |
Charlton Athletic | L1 | 2804.304527 |
Leyton Orient | L2 | 2803.121651 |
Swindon Town | L2 | 2777.087032 |
Watford | CHP | 2751.641527 |
Accrington Stanley | L1 | 2706.621788 |
Grimsby Town | L2 | 2653.709805 |
Hull City | CHP | 2626.05698 |
Blackpool | CHP | 2603.613716 |
Tranmere Rovers | L2 | 2571.050739 |
Bolton Wanderers | L1 | 2570.104312 |
Luton Town | CHP | 2569.24322 |
Bristol Rovers | L1 | 2552.672957 |
Bournemouth | EPL | 2545.352842 |
Stevenage Borough | L2 | 2532.233764 |
Harrogate Town | L2 | 2525.401762 |
Cambridge United | L1 | 2503.262907 |
Barnsley | L1 | 2424.322492 |
Lincoln City FC | L1 | 2414.584664 |
Everton | EPL | 2413.638857 |
Liverpool | EPL | 2406.098352 |
Leeds United | EPL | 2388.966341 |
Preston North End | CHP | 2388.594402 |
Brighton and Hove Albion | EPL | 2353.597824 |
Bradford City | L2 | 2345.305022 |
Wycombe Wanderers | L1 | 2319.525351 |
Sheffield Wednesday | L1 | 2285.827092 |
Blackburn Rovers | CHP | 2279.946168 |
Peterborough United | L1 | 2275.129343 |
Forrest Green Rovers | L1 | 2272.180646 |
Rochdale | L2 | 2269.709171 |
Burnley | CHP | 2269.154887 |
Southampton | EPL | 2267.113675 |
Wigan Athletic | CHP | 2239.711761 |
Salford City | L2 | 2236.227994 |
Shrewsbury Town | L1 | 2231.568891 |
Northampton Town | L2 | 2225.119602 |
Crewe Alexandra | L2 | 2214.580466 |
Doncaster Rovers | L2 | 2205.59141 |
Manchester United | EPL | 2180.361561 |
Oxford United | L1 | 2176.359243 |
Walsall | L2 | 2176.074434 |
Manchester City | EPL | 2174.695176 |
Stockport County | L2 | 2159.802133 |
Huddersfield Town | CHP | 2135.335073 |
MK Dons | L1 | 2125.685235 |
Cheltenham Town | L1 | 2110.792339 |
Port Vale | L1 | 2110.332034 |
Mansfield Town | L2 | 2064.237747 |
Rotherham United | CHP | 2049.048018 |
Coventry City | CHP | 2021.327189 |
West Bromwich Albion | CHP | 2008.167317 |
Birmingham City | CHP | 2007.252312 |
Sheffield United | CHP | 2005.506378 |
Derby County | L1 | 1980.135074 |
Stoke City | CHP | 1975.299586 |
Burton Albion | L1 | 1944.681918 |
Crystal Palace | EPL | 1835.178138 |
Nottingham Forest | EPL | 1801.300209 |
Wolverhampton Wanderers | EPL | 1799.949048 |
West Ham | EPL | 1785.365723 |
Tottenham Hotspur | EPL | 1750.095838 |
Chelsea | EPL | 1744.793609 |
Fulham | EPL | 1742.072913 |
Arsenal | EPL | 1741.906394 |
Brentford | EPL | 1727.724925 |
Aston Villa | EPL | 1723.783674 |
Leicester City | EPL | 1678.459261 |