0

Haversin 方程式を使用して緯度と経度を渡すと、半径 50 マイル以内のレコードを取得する MySQL ルーチンがあります。

これはうまく機能し、非常に高速ですが (82k レコードを検索していることを考えると)、POINT 列を使用して同様の手順を作成することでパフォーマンスを向上できると考えています。

そのため、テーブルに という追加の列を作成し、LocationPOINT のデータ型を指定し、データを更新して緯度と経度を列に渡しましたLocation。データは有効で、問題ありません。Spatial Index

Location問題は、列の代わりに列latを使用するように次のクエリを変換するにはどうすればよいかということlonです。

SET @LAT := '37.953';
SET @LON := '-105.688';

SELECT DISTINCT
BPZ.`store_id`,         
3956 * 2 * ASIN(SQRT(POWER(SIN((@LAT - abs(Z.`lat`)) * pi()/180 / 2),2) + COS(@LAT * pi()/180 ) * COS(abs(Z.`lat`) *  pi()/180) * POWER(SIN((@LON - Z.`lon`) *  pi()/180 / 2), 2))) as distance,
c.`name`,c.`address`,c.`city`,c.`state`,c.`phone`,c.`zip`,c.`premise_type`
FROM
`zip_codes` as Z, 
`brand_product_zip` as BPZ
LEFT JOIN `customers` c ON c.`store_id` = BPZ.`store_id`
WHERE
BPZ.`zip` = Z.`zip`
AND 
3956 * 2 * ASIN(SQRT(POWER(SIN((@LAT - abs(Z.`lat`)) * pi()/180 / 2),2) + COS(@LAT * pi()/180 ) * COS(abs(Z.`lat`) *  pi()/180) * POWER(SIN((@LON - Z.`lon`) *  pi()/180 / 2), 2))) <= 50
ORDER BY
distance LIMIT 20

これは以前に質問されたことを理解していますが、私が見るすべては、列ではなくに基づく計算を指してlatいますlonPOINT

更新されたコード:

SET @lat = 41.92;
SET @lon = -72.65;
SET @kmRange = 80.4672; -- = 50 Miles

SELECT *, (3956 * 2 * ASIN(SQRT(POWER(SIN((@lat - abs(`lat`)) * pi()/180 / 2),2) + COS(@lat * pi()/180 ) * COS(abs(`lat`) *  pi()/180) * POWER(SIN((lon - `lon`) *  pi()/180 / 2), 2)))) as distance
FROM    `zip_codes`
WHERE   MBRContains(LineString(Point(@lat + @kmRange / 111.1, @lon + @kmRange / (111.1 / COS(RADIANS(@lat)))), Point(@lat - @kmRange / 111.1, @lon - @kmRange / (111.1 / COS(RADIANS(@lat))))), `Location`)
Order By distance
LIMIT 20
4

2 に答える 2

2

ヒルベルト曲線の解を調べましたか? 空間インデックスは正確な解決策を提供しませんか? . mysql 空間インデックスを使用すると、mbrcontains を使用できます。

CREATE TABLE lastcrawl (id INT NOT NULL PRIMARY KEY, pnt POINT NOT NULL) ENGINE=MyISAM;

INSERT
INTO    lastcrawl
VALUES  (1, POINT(40, -100));

SET @lat = 40;
SET @lon = -100;

SELECT  *
FROM    lastcrawl
WHERE   MBRContains
                (
                LineString
                        (
                        Point
                                 (
                                 @lat + 10 / 111.1,
                                 @lon + 10 / ( 111.1 / COS(RADIANS(@lat)))
                                 ),
                        Point    (
                                 @lat - 10 / 111.1,
                                 @lon - 10 / ( 111.1 / COS(RADIANS(@lat)))
                                 )
                        ),
                pnt
                );

ここを見てください: MySQL - 空間点の近くを選択します。ここ: http://www.drdobbs.com/database/space-filling-curves-in-geospatial-appli/184410998

于 2013-05-29T14:00:52.523 に答える