简体   繁体   中英

Get Hotel Details from oracle database for given longitude and latitude

I have a table Hotel with columns as ID, NAME, DESCRIPTION, LONGITUDE, LATITUDE. Now I want to get all the hotels for a given radius(4 miles) and center as long lat value. I have implemented it as below query :

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;

It's giving correct recored. But It's very slow for large records. Can any one please suggest me alternative way to do it. I have done research on it and came to know that there is a geometry in oracle database. With the help of it we can acheive it by creating a geometry column in store table. But I don't know how to do it. Please suggest me how to do it.

Use Oracle's Spatial Data:

Oracle Setup :

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;

Query :

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'

Per @Gerald your query demands that the DB do the calculation for every record, it cannot use indexes.

You need to reformulate your query to

a) use indexes b) reduce the number of calculations

Therefore

1) index on latitude and longitude 2) Reformulate your query per @Gerald to a bounding box 3) If required put a final filter to check the exact calculation

Since people walk and drive mainly on a rectangular grid, the rectangular solution may be adequate.

Google can be the final arbiter and provide an accurate distance that takes in many local factors.

'Slow for large records' .... you possibly need to normalise, though many DB store data column-wise to avoid scanning more data than required - especially for indexed columns.

You may (more likely) mean 'slow for large datasets'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM