2016-01-19 20 views
0

我有一個酒店列與ID,名稱,描述,LONGITUDE,緯度。 現在,我想獲得給定半徑(4英里)內的所有酒店,並以中等長度的價值爲中心。我已執行它如下查詢:從oracle數據庫獲取酒店詳情給定經度和緯度

select NAME from (SELECT 
    NAME , (
    6371 * acos (
     cos (3.14*(52.047348)/180) 
     * cos(3.14*(latitude)/180) 
     * cos(3.14*(longitude)/180 - 3.14*(1.15542)/180) 
     + sin (3.14*(52.047348)/180) 
     * sin(3.14*(latitude)/180) 
    ) 
) AS distance 
FROM hotel where latitude is not null and longitude is not null) where distance < 4; 

這是給正確recored。 但是對於大型記錄來說非常慢。 任何人都可以請我提供替代方法來做到這一點。我已經完成了它的研究,並且知道oracle數據庫中有一個幾何體。在它的幫助下,我們可以通過在商店表中創建幾何列來實現它。 但我不知道該怎麼做。 請告訴我該怎麼做。

+1

M y方法是:計算具有給定半徑的矩形,並使用BETWEEN中的經度和緯度的最小值和最大值查找該區域中的酒店。 –

回答

0

Per @Gerald查詢要求數據庫對每條記錄進行計算,它不能使用索引。

您需要將您的查詢重新制定,以

一)使用索引 二)減少計算

因此數量

1)緯度和經度 2)重新擬訂根據您的查詢索引@Gerald到包圍盒 3)如果需要放入最終過濾器來檢查確切的計算

由於人們主要走路和駕駛一個矩形網格,矩形的解決方案可能就足夠了。

谷歌可以是最終的仲裁者,並提供一個準確的距離,需要考慮到很多當地因素。

'對於大記錄慢'...您可能需要進行標準化,儘管許多DB存儲數據按列方式以避免掃描更多數據(特別是對於索引列)。

您可以(更可能)的意思是「緩慢的大型數據集的

+0

你能告訴我如何使用經度和緯度的指數。此外,如果你能告訴我什麼是矩形解決方案,我該如何在這裏應用它。我是PLSQL的新手。 –

+0

RTFM - 在...上創建索引... 矩形==框形,並將添加緯度和縱向差異的大小以給出近似答案,極座標或徑向=絕對距離(您的解決方案)。 矩形近似計算和過濾要便宜得多。 – ChrisR

1

使用Oracle的Spatial數據:

甲骨文設置

CREATE TABLE Hotels (
    id  NUMBER(8,0), 
    name  VARCHAR2(255), 
    location SDO_GEOMETRY 
); 

INSERT INTO Hotels 
      SELECT 1, 'Hotel1', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(92,72,NULL), NULL, NULL) FROM DUAL 
UNION ALL SELECT 2, 'Hotel2', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(48,56,NULL), NULL, NULL) FROM DUAL 
UNION ALL SELECT 3, 'Hotel3', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(92,75,NULL), NULL, NULL) FROM DUAL; 

INSERT INTO USER_SDO_GEOM_METADATA (
    TABLE_NAME, COLUMN_NAME, DIMINFO, SRID 
) VALUES (
    'HOTELS', 
    'LOCATION', 
    SDO_DIM_ARRAY(
    SDO_DIM_ELEMENT('LONG', -180.0, 180.0, 0.5), 
    SDO_DIM_ELEMENT('LAT', -90.0, 90.0, 0.5) 
), 
    8307 
); 

CREATE INDEX HotelsTable_SIDX ON Hotels(location) INDEXTYPE IS MDSYS.SPATIAL_INDEX; 

查詢

SELECT * 
FROM Hotels 
WHERE sdo_within_distance (
     location, 
     SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(92,72,NULL), NULL, NULL), 
     'distance=4 unit=MILE' 
     ) = 'TRUE'