2011-01-18 2 views
9

mysqlデータベーステーブルに場所の緯度と経度の値を格納したいとします。将来を念頭に置いて、特定の場所の特定の半径内にこれらの場所を見つけることができるようにしたいと考えています。それで、緯度と経度の値をどのようなデータ型に格納すればいいですか?あなたはそうのような列のために作成するテーブル・スクリプトを私に提供することができます:MySQLの緯度と経度テーブルの設定

place_id | lat | long 

は、おそらく私が私が私が必要と表示されない場合があり、追加の情報を私に提供されます上記の表で行方不明です列あります現在の時刻?

ありがとうございました。

CREATE SPATIAL INDEX sx_place_location ON place (location) 

SELECT * 
FROM mytable 
WHERE MBRContains 
       (
       LineString 
         (
         Point($x - $radius, $y - $radius), 
         Point($x + $radius, $y + $radius) 
         ) 
       location 
       ) 
     AND Distance(Point($x, $y), location) <= $radius 

これは劇的に」のようなクエリの速度を改善します。

+0

[MySQLデータベースに緯度/経度を格納する際に使用する理想的なデータ型は何ですか?](http://stackoverflow.com/questions/159255/what-is-the-ideal-data-type -to-use-latitude-at-a-mysql) – Gajus

答えて

21

あなたがSPATIALインデックスとインデックス(あなたのテーブル型の場合MyISAM)できるデータ型Pointの焦がす列にポイントを保存すべきです指定された半径内のすべてを見つける "。

極座標(緯度と経度)ではなく平方の座標(東と北)を使用する方がよいことに注意してください。小さな半径の場合、それらは十分正確であり、計算は大幅に単純化されます。すべてのポイントが1つの裾野にあり、極から遠い場合は、1つの中央子午線を使用することができます。

もちろん極座標を使用することはできますが、MBRと距離を計算する式はより複雑になります。

+1

すべての私のテーブルは、私が外部キーを使用するので、InnoDBを使用しています。 InnoDBとMyISAMの両方にテーブルを置くことは問題ではありませんか? – Martin

+0

@Martin: 'MyISAM'はトランザクションレスなので、FOREIGN KEY制約は使用できません。 'SELECT'クエリについてのみ、異なるタイプのテーブルを混在させることに問題はありません。 – Quassnoi

+0

はい私は外部キーがMyISAMでは動作しないが、座標のテーブルを追加して、MyISAMと他のすべてのテーブルがInnoDBであることは問題ではないということを理解していますか? – Martin

0

私は何トンもの話題から数時間を掘り下げましたが、kmで定義された半径内の点を返すクエリは見つかりませんでした。 ST_Distance_Sphereはそれを行いますが、サーバーはST_Distance_Sphere()をサポートしていないMariaDB 5.5です。

ので、ここで何かの作業を取得するために管理

は教義2.5とDoctrine CrEOF空間ライブラリと互換性が私のソリューションです:

$sqlPoint = sprintf('POINT(%f %f)', $lng, $lat); 

    $rsm = new ResultSetMappingBuilder($this->manager); 
    $rsm->addRootEntityFromClassMetadata('ApiBundle\\Entity\\Place', 'p'); 

    $query = $this->manager->createNativeQuery(
     'SELECT p.*, AsBinary(p.location) as location FROM place p ' . 
     'WHERE (6371 * acos(cos(radians(Y(ST_GeomFromText(?)))) ' . 
     '* cos(radians(Y(p.location))) * cos(radians(X(p.location)) ' . 
     '- radians(X(ST_GeomFromText(?)))) + sin(radians(Y(ST_GeomFromText(?)))) * sin(radians(Y(p.location))))) <= ?', 
     $rsm 
    ); 

    $query->setParameter(1, $sqlPoint, 'string'); 
    $query->setParameter(2, $sqlPoint, 'string'); 
    $query->setParameter(3, $sqlPoint, 'string'); 
    $query->setParameter(4, $radius, 'float'); 

    $result = $query->getResult(); 

は、LNGとLAT固定点のXYであると仮定すると、場所が持つエンティティであります「場所」フィールドPOINTタイプ。 MySQLのparamバインディングに問題があるため、DQLを直接使用することができませんでした。そのため、低レベルのネイティブクエリが使用されています。 rsmは結果をエンティティオブジェクトにマップするために必要です。しかし、それなしで生きることができます。

気軽にお使いください。私はあなたが時間を節約することを願っています。