勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

MySQLで経度緯度から半径○Kmのデータを抽出する方法

   2024/01/13  MySQL / MariaDB

経度と緯度をtext型として格納しているMySQLのテーブルがあり、指定した経度緯度から半径○kmのデータ一覧を抽出したかった。以下に方法をメモ。

 

ソース

$km = 1; //半径km。半径500mを出したい場合は0.5にする
$sql = '
    SELECT
    *, 
    (6371 * ACOS(
        COS(RADIANS(緯度))
        * COS(RADIANS(lat))
        * COS(RADIANS(`long`) - RADIANS(経度))
        + SIN(RADIANS(緯度))
        * SIN(RADIANS(lat))
    )) AS distance
    FROM
        table
    WHERE status = 1 
    HAVING
        distance <= ' . $km . ' 
    ORDER BY
        distance
';

SQL文内のlongを`(アクサングラーブ)で囲んでいるのは予約語に当たるため。

 

その他

最初は経度と緯度から0.001ずつぐらい引いたり足したりして抽出したけどかなり位置情報が偏った。今回の方法はきっちりと指定した経度緯度を中心に抽出できた。

尚、経度緯度をMySQLで扱う場合はfloatやtextではなくgeometryを使うのが良いっぽい。

 

参考サイト

https://www.firstlogic.co.jp/blog/lab/raku/71

http://blog.asial.co.jp/473

 

予約語

https://dev.mysql.com/doc/refman/5.6/ja/reserved-words.html

 - MySQL / MariaDB

  関連記事

MySQLのトリガーを使用して特定のテーブルの操作を行った際に別テーブルにログを残す方法
MySQLのトリガーを使用して特定のテーブルの操作を行った際に別テーブルにログを残す方法

MySQLにトリガーという機能があるらしくどのようなものか調べたところ、事前に「 ...

MySQLでdatetime型にもインデックスを使用して高速化を図る方法
MySQLでdatetime型にもインデックスを使用して高速化を図る方法

ログ関連のデータを格納するテーブルがあり、集計を行う際に非常に時間がかかった。レ ...

InnoDBのオートインクリメントで抜け番が発生する原因について
InnoDBのオートインクリメントで抜け番が発生する原因について

MySQLのInnoDBでIDというカラムにオートインクリメント設定していたが、 ...

MySQLのRANK及びDENSE_RANK関数を用いてランキングを実装する方法
MySQLのRANK及びDENSE_RANK関数を用いてランキングを実装する方法

ランキング機能を実装する際、上位〇位までのデータをMySQLから持ってきて順位付 ...

MySQLにてdatetime型のカラムを整形し「年月日のみ形式」または「秒のみ省いた形式」で表示する方法
MySQLにてdatetime型のカラムを整形し「年月日のみ形式」または「秒のみ省いた形式」で表示する方法

MySQLにてdatetime型のカラムに登録日時等を格納しており、管理画面側で ...