sql >> データベース >  >> RDS >> Mysql

郵便番号の指定された距離内にあるすべての郵便番号を検索します

    これが私がかなり前に書いたもので、正しい方向にあなたを始めるかもしれません。

    VB.Netを要求しているときに、本当に必要なのは、「GreatCircle」を実行するクエリです。距離 「緯度と経度で識別される2点間の距離を決定するための計算。

    したがって、次の仮定を行います。

    1. 郵便番号データは1つのテーブルにあります。
    2. 上記のテーブルには、郵便番号のおおよその重心であるlatとlonの属性があります

    このようなものを使用して目的の結果セットを生成するLINQtoSQLクエリを使用できます

    Const EARTH_RADIUS As Single = 3956.0883313286095
    Dim radCvtFactor As Single = Math.PI / 180
    Dim zipCodeRadius As Integer = <Your Radius Value>
    
    Dim zipQry = From zc In db.ZipCodes 
                 Where zc.Zip = "<Your Zip Code>" _
                 Select zc.Latitude, 
                        zc.Longitude, 
                        ZipLatRads = RadCvtFactor * zc.Latitude, 
                        ZipLonRads = RadCvtFactor * zc.Longitude
    Dim zipRslt = zipQry.SingleOrDefault()
    If zipRslt IsNot Nothing Then
        Dim zcQry = From zc In db.ZipCodes _
                    Where zc.Latitude >= (zipRslt.Latitude - 0.5) And zc.Latitude <= (zipRslt.Latitude + 0.5) _
                    And zc.Longitude >= (zipRslt.Longitude - 0.5) And (zc.Longitude <= zipRslt.Longitude + 0.5) _
                    And Math.Abs(EARTH_RADIUS * (2 * Math.Atan2(Math.Sqrt(Math.Pow(Math.Sin(((RadCvtFactor * zc.Latitude) - zipRslt.ZipLatRads) / 2), 2) + _
                    Math.Cos(zipRslt.ZipLatRads) * Math.Cos(RadCvtFactor * zc.Latitude) * _
                    Math.Pow(Math.Sin(((RadCvtFactor * zc.Longitude) - zipRslt.ZipLonRads) / 2), 2)), _
                    Math.Sqrt(1 - Math.Pow(Math.Sin(((RadCvtFactor * zc.Latitude) - zipRslt.ZipLatRads) / 2), 2) + _
                    Math.Cos(zipRslt.ZipLatRads) * Math.Cos(RadCvtFactor * zc.Latitude) * _
                    Math.Pow(Math.Sin((RadCvtFactor * zc.Longitude) / 2), 2))))) <= zipCodeRadius _
                    Select zc
    End If
    

    複雑に見えます。ここSOには、アルゴリズムを説明できるはるかに賢い人々がいます。インターネットで見つけたSQLコードからこれを実装しただけです。どこからか思い出せません。 Google検索でそこにたどり着くはずです。

    最初のクエリ(zipQry)は、開始郵便番号の緯度と経度を度とラジアンの両方で返します。これらの結果は、2番目のクエリを実行するために使用されます。

    2番目のクエリのWHERE句の最初の部分:

    Where zc.Latitude >= (zipRslt.Latitude - 0.5) And zc.Latitude <= (zipRslt.Latitude + 0.5) _
    And zc.Longitude >= (zipRslt.Longitude - 0.5) And (zc.Longitude <= zipRslt.Longitude + 0.5) _
    

    調査する郵便番号のリストを絞り込んだだけで、クエリの実行が大幅に高速化されます。カリフォルニアで半径を検索するときにオハイオ州のすべての郵便番号をチェックしないように、緯​​度と経度に任意の量を追加します。残りはすべて、前述の大圏距離アルゴリズムの一部です。

    これは、効率を上げるために1つのクエリで実行できた可能性がありますが、当時はこの方法で必要だったため、理由がわかりませんでした。



    1. macOSにPostgreSQLをインストールする方法

    2. mysqlsprocのテーブル名に変数を使用する

    3. SQLServerの日付から短い月の名前を取得する5つの方法

    4. PostgreSQLで月ごとにグループ化する方法