【データベース】「住所データ 分割 政令指定都市 市区郡」でお困りの方へ

いわゆる最寄り駅検索や都道府県検索などを実装する場合、住所データをどうするか悩ましい所があるでしょう。一般的には JIS_X0402 という規格の市区町村コードを利用する場合が多いと思いますが、これをそのまま利用するのは私としてはイマイチです。
http://code.yokochou.com/x0402/01.html

私は札幌出身なので余計に感じることですが、

  • 「札幌市○○区」という括りとなっている。「札幌市」で検索したい場合に面倒
  • 「○○郡」がくっついている上に、「上川郡」の並びがぐちゃぐちゃで使えない

ということで、これをそのまま使うといい結果になりません。

市区町村を分割するような方法も見かけますがベストは方法は見当たりませんでした。

そこで、私なりに良さげな方法を考えたので書き残しておきます。

1. 総務省の「全国地方公共団体コード」を使う

http://www.soumu.go.jp/denshijiti/code.html

まず必須なのがコレ。区の情報がシートで分離されているので使いやすい。エクセルで開いて半角カナを全角に変換などした後に Google スプレッドシートにアップロード。CSVに変換してMySQLなどにインポートするという流れで簡単に用意できます。

市町村シートサンプル

このように、一旦「区」が入っていない市町村シートを調整してDBへインサート後、

政令指定都市シートサンプル

別シートの「政令指定都市」いわゆる区のデータを整備してインサートします。

2.「住所データ.jp」のデータと連携

総務省のデータだけだと、「○○郡」が無いんですよね…。ということで総務省のデータを元に、「住所データ.jp」のデータを一つ一つループで回し、「郡」を保存します。

http://jusyo.jp/sql/new.php

全国版のデータをインポートしておき、こんな感じのPHPを書きます(PDOを利用)

$exceptions = array();
$e = $pdo->prepare("SELECT * FROM ad_address GROUP BY ken_name, city_name ORDER BY id"); $e->execute();
while ($list = $e->fetch()) {
    if((substr_count($list['city_name'], '市') >= 1 || substr_count($list['city_name'], '区') >= 1) && substr_count($list['city_name'], '郡') >= 1) {
        //余市郡、芳賀郡市貝町などが十数件出現
        $exceptions[] = $list['city_name'];
        $exceptions[] = mb_convert_kana($list['city_furi'],"c");
    } else if(substr_count($list['city_name'], '郡') >= 2) {
        //赤穂郡上郡町が出現
        $exceptions[] = $list['city_name'];
        $exceptions[] = mb_convert_kana($list['city_furi'],"c");
    }  else if(substr_count($list['city_name'], '郡') === 1) {
        if(substr_count($list['city_furi'], 'グン') >= 2) {
            //北群馬郡榛東村、北群馬郡吉岡町が出現
            $exceptions[] = $list['city_name'];
            $exceptions[] = mb_convert_kana($list['city_furi'],"c");
        } else {
            $str = explode("郡",$list['city_name']);

            //都道府県
            $pref = $list['ken_name'];
            //市区町村
            $city = $str[1];
            //郡
            $county = $str[0].'郡';
            //郡のよみ
            $k_county = mb_convert_kana(explode("グン",$list['city_furi'])[0],"c").'ぐん';
            //総務省データを入れたDBに保存します。
            $pdo->prepare("UPDATE `soumu_address` SET county = ?, k_county = ? WHERE pref = ? AND city = ? ")
                ->execute(array($county, $k_county, $pref, $city));
        }
    }
}

//例外が発生した市区町村が表示されるので手動対応
var_dump($exceptions);

市なのに名前に「郡」があったり、名前に「郡」が2つあったり、読み仮名に「グン」が2つあるような例外は手動対応となりますが、それ以外はプログラムで追加されます。

3. 例外を手動対応

上記で発生した例外を手動で入れたり、必要に応じて調整を加えていきましょう。

まずは「郡のない町村」をあぶり出します。

select * from soumu_address where `county` = '' and (city like '%村' or city like '%町')

東京都は例外的に、郡のない町が9つ存在するので注意して下さい。

大島町, 利島村, 新島村, 神津島村, 三宅村, 御蔵島村, 八丈町, 青ヶ島村, 小笠原村

このうち、「三宅村」と「八丈島」に関しては、日本郵政の郵便番号データベースに合わせるなら、それぞれ「三宅島三宅村」「八丈島八丈町」になります。島の扱いをどうするかは状況により異なるでしょうが、私は島含め市区町村名(city)にしています。

これとは別に、「総務省のデータは存在するのに住所データ.jpに存在しない」町村があれば手動対応します。執筆時点では、高知県の梼原町、福岡県の須恵町び漢字が異なっていました。ほとんどのシステムでは郵便番号DBを使っているため、私はこちらに統一。

「梼原町」→「檮原町」
「須恵町」→「須惠町」

また、東京23区は例外的に「市」が存在していません。こちらも注意しましょう。

1943年(昭和18年)6月までは市制を敷き東京府にある東京市であったが、同府・市が都制に移行したことで東京市とはいえなくなり、主にこのように呼称されることとなった。東京23区または東京特別区とも呼ばれる。
https://ja.wikipedia.org/wiki/%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%8C%BA%E9%83%A8