Saya mencoba menghitung jarak antara dua posisi di peta. Saya telah menyimpan data saya: Bujur, Lintang, X POS, Y POS.
Saya sebelumnya telah menggunakan potongan di bawah ini.
DECLARE @orig_lat DECIMAL
DECLARE @orig_lng DECIMAL
SET @orig_lat=53.381538 set @orig_lng=-1.463526
SELECT *,
3956 * 2 * ASIN(
SQRT( POWER(SIN((@orig_lat - abs(dest.Latitude)) * pi()/180 / 2), 2)
+ COS(@orig_lng * pi()/180 ) * COS(abs(dest.Latitude) * pi()/180)
* POWER(SIN((@orig_lng - dest.Longitude) * pi()/180 / 2), 2) ))
AS distance
--INTO #includeDistances
FROM #orig dest
Namun saya tidak mempercayai data yang keluar dari ini, tampaknya memberikan hasil yang sedikit tidak akurat.
Beberapa contoh data jika Anda membutuhkannya
Latitude Longitude Distance
53.429108 -2.500953 85.2981833133896
Adakah yang bisa membantu saya dengan kode saya, saya tidak keberatan jika Anda ingin memperbaiki apa yang sudah saya miliki jika Anda memiliki cara baru untuk mencapai ini, itu akan sangat bagus.
Sebutkan dalam unit pengukuran hasil Anda.
sql
sql-server
tsql
math
sql-server-2008-r2
Waller
sumber
sumber
Jawaban:
Karena Anda menggunakan SQL Server 2008, Anda memiliki
geography
tipe data yang tersedia, yang dirancang untuk jenis data ini:DECLARE @source geography = 'POINT(0 51.5)' DECLARE @target geography = 'POINT(-3 56)' SELECT @source.STDistance(@target)
Memberi
---------------------- 538404.100197555 (1 row(s) affected)
Memberitahu kami jaraknya sekitar 538 km dari (dekat) London ke (dekat) Edinburgh.
Tentu akan ada sejumlah pembelajaran yang harus dilakukan terlebih dahulu, tetapi begitu Anda mengetahuinya, itu jauh lebih mudah daripada menerapkan perhitungan Haversine Anda sendiri; ditambah Anda mendapatkan BANYAK fungsi.
Jika Anda ingin mempertahankan struktur data yang ada, Anda masih dapat menggunakan
STDistance
, dengan membuatgeography
instance yang sesuai menggunakanPoint
metode:DECLARE @orig_lat DECIMAL(12, 9) DECLARE @orig_lng DECIMAL(12, 9) SET @orig_lat=53.381538 set @orig_lng=-1.463526 DECLARE @orig geography = geography::Point(@orig_lat, @orig_lng, 4326); SELECT *, @orig.STDistance(geography::Point(dest.Latitude, dest.Longitude, 4326)) AS distance --INTO #includeDistances FROM #orig dest
sumber
Fungsi di bawah ini memberikan jarak antara dua koordinat geografis dalam mil
create function [dbo].[fnCalcDistanceMiles] (@Lat1 decimal(8,4), @Long1 decimal(8,4), @Lat2 decimal(8,4), @Long2 decimal(8,4)) returns decimal (8,4) as begin declare @d decimal(28,10) -- Convert to radians set @Lat1 = @Lat1 / 57.2958 set @Long1 = @Long1 / 57.2958 set @Lat2 = @Lat2 / 57.2958 set @Long2 = @Long2 / 57.2958 -- Calc distance set @d = (Sin(@Lat1) * Sin(@Lat2)) + (Cos(@Lat1) * Cos(@Lat2) * Cos(@Long2 - @Long1)) -- Convert to miles if @d <> 0 begin set @d = 3958.75 * Atan(Sqrt(1 - power(@d, 2)) / @d); end return @d end
Fungsi di bawah ini memberikan jarak antara dua koordinat geografis dalam kilometer
CREATE FUNCTION dbo.fnCalcDistanceKM(@lat1 FLOAT, @lat2 FLOAT, @lon1 FLOAT, @lon2 FLOAT) RETURNS FLOAT AS BEGIN RETURN ACOS(SIN(PI()*@lat1/180.0)*SIN(PI()*@lat2/180.0)+COS(PI()*@lat1/180.0)*COS(PI()*@lat2/180.0)*COS(PI()*@lon2/180.0-PI()*@lon1/180.0))*6371 END
Fungsi di bawah ini memberikan jarak antara dua koordinat geografis dalam kilometer menggunakan tipe data Geografi yang diperkenalkan di sql server 2008
DECLARE @g geography; DECLARE @h geography; SET @g = geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 4326); SET @h = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326); SELECT @g.STDistance(@h);
Pemakaian:
select [dbo].[fnCalcDistanceKM](13.077085,80.262675,13.065701,80.258916)
Referensi: Ref1 , Ref2
sumber
Sepertinya Microsoft menyerang otak semua responden lain dan membuat mereka menulis solusi serumit mungkin. Berikut adalah cara termudah tanpa pernyataan fungsi / deklarasi tambahan:
SELECT geography::Point(LATITUDE_1, LONGITUDE_1, 4326).STDistance(geography::Point(LATITUDE_2, LONGITUDE_2, 4326))
Cukup mengganti data Anda bukan
LATITUDE_1
,LONGITUDE_1
,LATITUDE_2
,LONGITUDE_2
misalnya:SELECT geography::Point(53.429108, -2.500953, 4326).STDistance(geography::Point(c.Latitude, c.Longitude, 4326)) from coordinates c
sumber
Create Function [dbo].[DistanceKM] ( @Lat1 Float(18), @Lat2 Float(18), @Long1 Float(18), @Long2 Float(18) ) Returns Float(18) AS Begin Declare @R Float(8); Declare @dLat Float(18); Declare @dLon Float(18); Declare @a Float(18); Declare @c Float(18); Declare @d Float(18); Set @R = 6367.45 --Miles 3956.55 --Kilometers 6367.45 --Feet 20890584 --Meters 6367450 Set @dLat = Radians(@lat2 - @lat1); Set @dLon = Radians(@long2 - @long1); Set @a = Sin(@dLat / 2) * Sin(@dLat / 2) + Cos(Radians(@lat1)) * Cos(Radians(@lat2)) * Sin(@dLon / 2) * Sin(@dLon / 2); Set @c = 2 * Asin(Min(Sqrt(@a))); Set @d = @R * @c; Return @d; End GO
Pemakaian:
pilih dbo.DistanceKM (37.848832506474, 37.848732506474, 27.83935546875, 27.83905546875)
Keluaran:
0,02849639
Anda dapat mengubah parameter @R dengan float yang dikomentari.
sumber
Karena Anda menggunakan SQL 2008 atau yang lebih baru, saya sarankan untuk memeriksa GEOGRAFI tipe data . SQL telah membangun dukungan untuk kueri geospasial.
misalnya Anda akan memiliki kolom di tabel Anda dengan tipe GEOGRAFI yang akan diisi dengan representasi geospasial dari koordinat (lihat referensi MSDN yang ditautkan di atas untuk contoh). Jenis data ini kemudian memaparkan metode yang memungkinkan Anda melakukan seluruh host kueri geospasial (misalnya menemukan jarak antara 2 titik)
sumber
Selain jawaban sebelumnya, berikut ini cara menghitung jarak di dalam SELECT:
CREATE FUNCTION Get_Distance ( @La1 float , @Lo1 float , @La2 float, @Lo2 float ) RETURNS TABLE AS RETURN -- Distance in Meters SELECT GEOGRAPHY::Point(@La1, @Lo1, 4326).STDistance(GEOGRAPHY::Point(@La2, @Lo2, 4326)) AS Distance GO
Pemakaian:
select Distance from Place P1, Place P2, outer apply dbo.Get_Distance(P1.latitude, P1.longitude, P2.latitude, P2.longitude)
Fungsi skalar juga berfungsi tetapi sangat tidak efisien saat menghitung data dalam jumlah besar.
Saya harap ini bisa membantu seseorang.
sumber