2012-10-02 6 views
8

मैं सड़कों और होटलों के बारे में डेटा संग्रहीत करने के लिए MySQL Spatial Extensions का उपयोग कर रहा हूं। मैं होटल डेटा को प्वाइंट के रूप में संग्रहीत करता हूं, जबकि मैं लाइन डेटा को लाइनस्ट्रिंग के रूप में संग्रहीत करता हूं। सारणी इस तरह दिखती हैंMySQL स्थानिक एक्सटेंशन का उपयोग करके एक बिंदु से एन निकटतम लाइनस्ट्रिंग खोजें

CREATE TABLE IF NOT EXISTS `Hotels` (
    `id` int unsigned NOT NULL AUTO_INCREMENT, 
    `name` text, 
    `coordinate` point NOT NULL, 
    PRIMARY KEY (`id`), 
    SPATIAL KEY `coordinate` (`coordinate`), 
) 

CREATE TABLE IF NOT EXISTS `Roads` (
    `id` int unsigned NOT NULL AUTO_INCREMENT, 
    `name` text, 
    `route` linestring NOT NULL, 
    PRIMARY KEY (`id`), 
    SPATIAL KEY `coordinate` (`route`), 
) 

एक उदाहरण का दृश्य इस तरह होगा।

http://i.stack.imgur.com/8IVVA.png

मेरे समस्या एक नंबर एन और एक बिंदु पी, SQL क्वेरी बिंदु पी से एन सड़कों निकटतम खोजने के लिए क्या है दिया जाता है? दूरी को ऊपर दिखाए गए बिंदु पर सड़क के एक सेगमेंट के बीच सबसे छोटी लंबवत दूरी से परिभाषित किया गया है। (हालांकि वास्तविकता में, निकटतम दूरी राजमार्ग द्वार और एक होटल के बीच होनी चाहिए, लेकिन इस मामले में, हम किसी भी बिंदु से राजमार्ग में प्रवेश कर सकते हैं: पी)

यदि इसके लिए कोई एकल SQL कथन समाधान नहीं है समस्या, एक मध्यस्थ एसक्यूएल क्वेरी और एक पोस्ट प्रोसेसिंग मेरे लिए स्वीकार्य है। लेकिन एक कुशल एसक्यूएल क्वेरी और डेटा को पोस्ट-प्रोसेस करने का तरीका क्या होगा?

+0

क्या आपने अभी तक अपना जवाब प्राप्त कर लिया है? :) – bonCodigo

+0

कृपया सुनिश्चित करें कि आप MySQL 5.5 का उपयोग कर रहे हैं अन्यथा स्थानिक कार्यक्षमता आपके प्रश्न का उत्तर देने के लिए पर्याप्त लागू नहीं की गई है – TheSteve0

उत्तर

2

आप डेटाबेस में दो कार्य बना सकते हैं:

  1. दूरी: यह दो अंक
  2. के बीच आप दूरी दे देंगे
  3. DistanceFromLine: यहाँ दूरी लाइन में हर बिंदु से गणना की जाएगी, और आप दे देंगे सबसे छोटी दूरी

अपने बिंदु और रेखाओं के बीच की दूरी की तुलना करें और सबसे छोटा चुनें।

यहाँ दूरी समारोह


delimiter // 

CREATE FUNCTION distance (latA double, lonA double, latB double, LonB double) 
RETURNS double DETERMINISTIC 
    BEGIN 
     SET @RlatA = radians(latA); 
     SET @RlonA = radians(lonA); 
     SET @RlatB = radians(latB); 
     SET @RlonB = radians(LonB); 
     SET @deltaLat = @RlatA - @RlatB; 
     SET @deltaLon = @RlonA - @RlonB; 
     SET @d = SIN(@deltaLat/2) * SIN(@deltaLat/2) + 
     COS(@RlatA) * COS(@RlatB) * SIN(@deltaLon/2)*SIN(@deltaLon/2); 
     RETURN 2 * ASIN(SQRT(@d)) * 637101; 
    END// 

यहाँ है DistanceFromLine समारोह है:


DROP function IF EXISTS `DistanceFromLine`; 
delimiter // 
    CREATE FUNCTION `DistanceFromLine`(
    route LINESTRING, point1 POINT 
    ) RETURNS INT DETERMINISTIC 
     BEGIN 
     DECLARE a INT Default 0 ; 
     DECLARE minDistance INT Default 0; 
     DECLARE currentDistance INT Default 0; 
     DECLARE currentpoint point ; 
     DECLARE size INT Default 0 ; 
     SET size = NumPoints(route); 
       simple_loop: LOOP 
     SET a = a+1; 
     SET currentpoint = PointN(route,a); 
     SET currentDistance = Distance(X(point1), Y(point1),  
       X(currentpoint),Y(currentpoint)); 

     IF a = 1 THEN 
     SET minDistance = currentDistance; 
      END IF; 

     IF currentDistance < minDistance THEN 
     SET minDistance = currentDistance; 
     END IF; 
     IF a=size THEN 
       LEAVE simple_loop; 
     END IF; 
      END LOOP simple_loop; 
    RETURN (minDistance); 
END// 

0

यह था एक बहुत ही उपयोगी एक मेरे लिए झुकाओ, लेकिन मैं MySQL 5.7.18 का उपयोग कर रहा हूं, जिसमें अधिक उन्नत या सिर्फ अलग भौगोलिक क्वेरी फ़ंक्शन हैं। तैनात दूरी फ़ंक्शन की अब आवश्यकता नहीं है- ST_Distance_Sphere का उपयोग करें। तो यहाँ एक ही कोड DistanceFromLine आधुनिक (5.7.6+) MySQL के अनुरूप नहीं बना की एक अद्यतन ...

DROP function IF EXISTS `DistanceFromLine`; 
delimiter // 
    CREATE FUNCTION `DistanceFromLine`(
    route LINESTRING, point1 POINT 
    ) RETURNS INT DETERMINISTIC 
     BEGIN 
     DECLARE a INT Default 0 ; 
     DECLARE minDistance INT Default 0; 
     DECLARE currentDistance INT Default 0; 
     DECLARE currentpoint point ; 
     DECLARE size INT Default 0 ; 
     SET size = ST_NumPoints(route); 
       simple_loop: LOOP 
     SET a = a+1; 
     SET currentpoint = ST_PointN(route,a); 
     SET currentDistance = ST_Distance_Sphere(point1,currentpoint); 

     IF a = 1 THEN 
     SET minDistance = currentDistance; 
      END IF; 

     IF currentDistance < minDistance THEN 
     SET minDistance = currentDistance; 
     END IF; 
     IF a=size THEN 
       LEAVE simple_loop; 
     END IF; 
      END LOOP simple_loop; 
    RETURN (minDistance); 
END// 
0

मैं भी इस मुद्दे पर काम कर रहा है, लेकिन दुर्भाग्य से होटल निकटवर्ती सड़क ढूंढना है प्रतिकूल समाधान। मैंने पाया है कि सड़क पर प्रवेश द्वार निश्चित उत्तर है। दूसरे शब्दों में पता। इसका मतलब है कि पता तालिका और मिलान बिंदु निकटतम पता सड़क पर है।

संबंधित मुद्दे