দুটি পয়েন্ট (অক্ষাংশ, দ্রাঘিমাংশ) এর মধ্যে দূরত্ব গণনা করা হচ্ছে


89

আমি একটি মানচিত্রে দুটি অবস্থানের মধ্যে দূরত্ব গণনা করার চেষ্টা করছি am আমি আমার ডেটাতে সঞ্চয় করেছি: দ্রাঘিমাংশ, অক্ষাংশ, এক্স পোস, ওয়াই পস।

আমি আগে নীচের স্নিপেট ব্যবহার করে আসছি।

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

যাইহোক আমি এ থেকে আসা ডেটাগুলিতে বিশ্বাস করি না, মনে হচ্ছে এটি কিছুটা ভুল ফলাফল দিয়েছে।

আপনার প্রয়োজনে কিছু নমুনা ডেটা

Latitude        Longitude     Distance 
53.429108       -2.500953     85.2981833133896

আমার কোডটি সম্পর্কে যে কেউ আমাকে সাহায্য করতে পারে, আপনি যদি ইতিমধ্যে আমার কাছে যা ঠিক আছে তা ঠিক করতে চান আপনি যদি এটি অর্জন করার নতুন উপায় থাকে তবে তা দারুণ হবে I

আপনার ফলাফলগুলি পরিমাপের কোন ইউনিটে রয়েছে দয়া করে তা জানান।


অতিরিক্ত / 2 দ্বারা আপনার যুক্তিকে সাইন দিয়ে ভাগ করা উচিত নয়। এছাড়াও আপনি পৃথিবীর ব্যাসার্ধের আরও যথাযথতা পেতে পারেন, পাশাপাশি জিপিএস সিস্টেম দ্বারা ব্যবহৃত কিছু ডেটাম ব্যবহার করে (ডাব্লুজিএস
-৪৪

@ ওয়ালার, আপনি এটি অর্জনের জন্য ভূগোল / জ্যামিতি (স্থানিক) প্রকারটি ব্যবহার করেন না কেন?
হাবিব

4
আমি গণিতের সাথে আপনার গণনা পরীক্ষা করেছি; এটি মনে করে যে বিধিবদ্ধ মাইলের দূরত্ব (5280 ফুট) 42.997, যা আপনাকে বোঝায় যে আপনার গণনাটি কিছুটা ভুল নয় , বরং এটি মারাত্মকভাবে ভুল
হাই পারফরম্যান্স মার্ক

উত্তর:


130

যেহেতু আপনি এসকিউএল সার্ভার ২০০৮ ব্যবহার করছেন, আপনার কাছে geographyডেটা টাইপ উপলব্ধ রয়েছে, যা ঠিক এই ধরণের ডেটার জন্য ডিজাইন করা হয়েছে:

DECLARE @source geography = 'POINT(0 51.5)'
DECLARE @target geography = 'POINT(-3 56)'

SELECT @source.STDistance(@target)

দেয়

----------------------
538404.100197555

(1 row(s) affected)

আমাদের বলার এটি লন্ডন থেকে (কাছাকাছি) এডিনবার্গের প্রায় 538 কিলোমিটার দূরে।

স্বাভাবিকভাবেই প্রথমে শিখার পরিমাণ থাকবে তবে এটি একবার জানলে এটি আপনার নিজের হ্যাভারসাইন গণনা কার্যকর করার চেয়ে অনেক বেশি সহজ; এছাড়াও আপনি প্রচুর কার্যকারিতা পান।


আপনি যদি আপনার বিদ্যমান ডেটা কাঠামো ধরে রাখতে চান তবে আপনি পদ্ধতিটি ব্যবহার করে STDistanceউপযুক্ত geographyউদাহরণগুলি তৈরি করে এখনও ব্যবহার করতে পারেন Point:

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

6
@ নেজাম নং - প্রাইম মেরিডিয়ান পশ্চিমের জায়গাগুলির জন্য দ্রাঘিমাংশ নেতিবাচক হবে এবং এর পূর্ব স্থানগুলির জন্য ইতিবাচক হবে
আকাশম ২

তুমি আমার দিন বাঁচিয়েছ! .. অনেক অনেক ধন্যবাদ!
ধ্রুমিল ভানখার

4
বিল্ট ইন ফাংশনটি ব্যবহার করা খুব ধীর বলে মনে হচ্ছে। উদাহরণস্বরূপ, 100,000 আইটেমের লুপে এটি আমার ব্যবহারকারীর সংজ্ঞায়িত ফাংশনটির জন্য 1.4 সেকেন্ডের পরিবর্তে 23 সেকেন্ড সময় নেয় (দুরাইয়ের উত্তর দেখুন)।
নিকজি

4
কেবলমাত্র ইটিএল অ্যাপ্লিকেশনটির জন্য @ আকাশের সুপারিশের জন্য সুপারিশের সুপারিশটি নিশ্চিত করতে এবং এটি নিশ্চিত করতে চেয়েছিলেন, স্থানিক সূচকগুলি প্রয়োগ করার পরে পার্থক্যটি ছিল বেশ কয়েকটি মাত্রার আরও ভাল আদেশ
বিল

4
এফওয়াইআই: পয়েন্ট (লম্বিটুড ল্যাটিটুড) যেখানে ভূগোল :: পয়েন্ট (ল্যাটিটুড, লঙ্গিটুড, 4326)
মেজেন

42

নীচের ফাংশনটি মাইলের মধ্যে দুটি ভৌগলিক যোগাযোগের মধ্যে দূরত্ব দেয়

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 

নীচের ফাংশনটি কিলোমিটারে দুটি জিওকোর্ডিনেটের মধ্যে দূরত্ব দেয়

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

নীচের ফাংশনটি ভূগোল ডেটা টাইপ ব্যবহার করে কিলোমিটারে দুটি জিওকোর্ডিনেটের মধ্যে দূরত্ব দেয় যা স্কেল সার্ভার ২০০৮ সালে চালু হয়েছিল

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);

ব্যবহার:

select [dbo].[fnCalcDistanceKM](13.077085,80.262675,13.065701,80.258916)

তথ্যসূত্র: রেফ 1 , রেফ 2


4
একটি জিপ কোড থেকে দূরত্বে অর্ডার করা বিভিন্ন ইভেন্টের জিপ কোডগুলির বিপরীতে 35 কে জিপ কোডগুলির জন্য আমার দূরত্ব গণনা করা দরকার। ভূগোলের ডেটা টাইপ ব্যবহার করে গণনা করার জন্য এটি স্থানাঙ্কের তালিকার খুব বড় ছিল। আমি যখন উপরের সিঙ্গল-লাইনের ট্রিগ ফাংশন ভিত্তিক সমাধানটি ব্যবহার করতে স্যুইচ করেছি, তখন এটি অনেক দ্রুত ছড়িয়ে পড়ে। সুতরাং কেবল একটি দূরত্ব গণনা করতে ভূগোলের ধরণগুলি ব্যবহার করা ব্যয়বহুল বলে মনে হয়। ক্রেতা হুঁশিয়ার.
টোবালা

কোয়েরির যেখানে ক্লাউজে দূরত্ব গণনা করার জন্য খুব দরকারী। আমাকে "সেট @ ডি =" এক্সপ্রেশনটির চারপাশে একটি এবিএস () গুটিয়ে রাখতে হয়েছিল, কারণ আমি এমন কিছু ঘটনা পেয়েছি যেখানে ফাংশনটি নেতিবাচক দূরত্ব ফিরে পেয়েছে।
জো

4
"কিলোমিটারে দুটি জিওকোর্ডিনেটের মধ্যে দূরত্ব" জন্য কাজ ব্যর্থ হয় যদি আমরা 2 টি সমান পয়েন্টের তুলনা করি তবে এটি আপনাকে ত্রুটি দেয় "একটি অবৈধ ভাসমান পয়েন্ট অপারেশন ঘটেছে"
আরআরএম

4
এটি দুর্দান্ত ছিল তবে স্বল্প দূরত্বের জন্য কাজ করে না কারণ "দশমিক (8,4)" পর্যাপ্ত নির্ভুলতা সরবরাহ করে না।
প্রভাবশালী

4
@ তথ্যপ্রযুক্তিটি সঠিক, এটি স্বল্প দূরত্বের জন্য কার্যকর নয় (আমার ক্ষেত্রে 5 মাইল)
রজার

16

দেখে মনে হচ্ছে মাইক্রোসফ্ট অন্য সমস্ত উত্তরদাতাদের মস্তিস্ক আক্রমণ করেছে এবং তাদের যতটা সম্ভব জটিল সমাধান লিখতে বাধ্য করেছে। কোনও অতিরিক্ত ফাংশন / ঘোষণা বিবৃতি ছাড়াই এখানে সহজ উপায়:

SELECT geography::Point(LATITUDE_1, LONGITUDE_1, 4326).STDistance(geography::Point(LATITUDE_2, LONGITUDE_2, 4326))

কেবলমাত্র আপনার ডেটা প্রতিস্থাপন পরিবর্তে LATITUDE_1, LONGITUDE_1, LATITUDE_2, LONGITUDE_2যেমন:

SELECT geography::Point(53.429108, -2.500953, 4326).STDistance(geography::Point(c.Latitude, c.Longitude, 4326))
from coordinates c

4
রেফারেন্সের জন্য: এসটিডিস্টেন্স () আপনার ভূগোলের ডেটা সংজ্ঞায়িত করা হয়েছে এমন স্থানিক রেফারেন্স সিস্টেমের পরিমাপের রৈখিক এককে দূরত্ব দেয়। আপনি এসআরআইডি 4326 ব্যবহার করছেন, যার অর্থ এসটিডিস্টেন্স () মিটারে দূরত্বে ফিরে আসে।
ব্রায়ান স্টাম্প

5
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

ব্যবহার:

dbo.Distance নির্বাচন করুন (37.848832506474, 37.848732506474, 27.83935546875, 27.83905546875)

ফলাফল:

0,02849639

আপনি মন্তব্য করা ফ্লোট সহ @ আর প্যারামিটার পরিবর্তন করতে পারেন।


নিখুঁতভাবে কাজ করে
তেজস্বী হেগদে

4

আপনি এসকিউএল ২০০৮ বা তার পরে যেমন ব্যবহার করছেন, আমি জিওগ্রাফি ডেটা ধরণের পরীক্ষা করার পরামর্শ দেব । এসকিউএল ভূ-স্থান সংক্রান্ত প্রশ্নের জন্য সমর্থন তৈরি করেছে support

উদাহরণস্বরূপ আপনার জিওগ্রাফি টাইপের টেবিলটিতে আপনার একটি কলাম রয়েছে যা স্থানাঙ্কগুলির একটি ভূ-স্থানিক উপস্থাপনা দিয়ে তৈরি করা হবে (উদাহরণগুলির জন্য উপরে লিঙ্কযুক্ত এমএসডিএন রেফারেন্সটি দেখুন)। এই ডেটাটাইপটি আপনাকে ভূ-স্থান সংক্রান্ত প্রশ্নের পুরো হোস্ট সম্পাদনের অনুমতি দেয় এমন পদ্ধতিগুলি উন্মুক্ত করে (উদাহরণস্বরূপ 2 পয়েন্টের মধ্যে দূরত্ব সন্ধান করা)


কেবল যোগ করার জন্য, আমি ভৌগলিক ক্ষেত্রের প্রকারটি চেষ্টা করেছিলাম, তবে ডুরাইয়ের ফাংশনটি (সরাসরি দ্রাঘিমাংশ এবং অক্ষাংশ মানের ব্যবহার করে) আরও দ্রুত হতে পেয়েছি । আমার উদাহরণটি এখানে দেখুন: stackoverflow.com/a/37326089/391605
মাইক গ্লেডহিল

1

পূর্ববর্তী উত্তরগুলি ছাড়াও, এখানে একটি নির্বাচনের ভিতরে দূরত্ব গণনা করার একটি উপায়:

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

ব্যবহার:

select Distance
from Place P1,
     Place P2,
outer apply dbo.Get_Distance(P1.latitude, P1.longitude, P2.latitude, P2.longitude)

স্কেলার ফাংশনগুলিও কাজ করে তবে বিপুল পরিমাণে ডেটা গণনা করার সময় এগুলি খুব অদক্ষ।

আমি আশা করি এটি কারও সাহায্য করবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.