2

すべての住所の番地を次のような順序で格納した郵便番号データベースを購入しました。

1002-1004;1101-1105;1102-1104;1201-1205;1202-1204;1301-1305;1302-1304;1401-1405;1402-1404;1501-1505;1502-1504;1601-1605;1602-1604;1701-1705;1702-1704;1801-1805;1802-1804;1902-1904;1901-1905;2007;2006-2012;2011-2013;2106-2112;2107-2113;2206-2212;2207-2213;2306-2312;2307-2313;2406-2412;2407-2413;2506-2512;2507-2513;2606-2612;2607-2613;2706-2712;2707-2713;2806-2812;2807-2813;2906-2912;2907-2913;3014-3020;3015-3021;3114-3120;3115-3121;3214-3220;3215-3221;3314-3320;3315-3321;3414-3420;3415-3421

これは最も長いものですが、より短いリスト、範囲のみ、または 1 つの数値のみの場合もあります。郵便番号と番地のみを使用して住所を検索する方法を見つけようとしています。

明らかに、データベース内の各エントリを最小/最大値で分割できますが、これにより、更新がさらに大きなタスクになります。

MySQLクエリでこれを実現する方法はありますか? または、ここで PHP (私の場合) に依存する必要がありますか?

心よりお待ちしております...

4

1 に答える 1

1

あなたが示したように、数値(1017など)が文字列として保存された一連の範囲内にあるかどうかをチェックするための単純なネイティブ関数はありません。

簡単に言えば、いいえ、この種の検索は MySQL では実行できません。

より長い答えは、非現実的ではありますが、そのリスト内の各範囲の個々の最小および最大コンポーネントを引き出すために必要な種類の文字列操作を実行することは可能です。

まず、パフォーマンスの観点から、これは非現実的です (すべての検索でそのような重労働を実行したくないでしょう。第二に、そのような文字列操作を行うために必要な歪んだ SQL のため、非現実的です。

MySQL パフォーマンスの観点から、このタイプの検索を実行するためのはるかに優れた方法は、その範囲のリストをテーブル内の個別の行として表すことです。

r_mod r_min r_max
----- ----- -----
    0  1002  1004
    1  1101  1105
    0  1102  1104
    1  1201  1205

MySQL にこれらの範囲リストのそれぞれを個別の行の範囲に「分割」させ、各リストの末尾にセミコロンを付けるには、次のようなクエリを実行できます。

SELECT n.i
     , SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(d.foo,';', n.i ),';',-1),'-', 1 ),'-',-1)%2 AS r_mod
     , SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(d.foo,';', n.i ),';',-1),'-', 1 ),'-',-1)/1 AS r_min
     , SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(d.foo,';', n.i ),';',-1),'-', 2 ),'-',-1)/1 AS r_max
  FROM (SELECT '1002-1004;1101-1105;1102-1104;1201-1205;1202-1204;1301-1305;' AS foo) d
 CROSS
  JOIN ( SELECT h.d*100+t.d*10+o.d+1 AS i
           FROM (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
                 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 
                 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) o
          CROSS
           JOIN (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
                  UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 
                  UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t
          CROSS 
           JOIN (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
                  UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
                  UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) h
       ) n
HAVING r_max > 0

(そのクエリの場合、範囲リスト文字列には末尾にセミコロンを追加する必要があり、そのクエリはリストごとに最初の 1000 エントリのみを取得することに注意してください。) そのような構造を考えると、理論的には、「検索」を行うことが可能です。数値比較:

avalue MOD 2 = r_mod AND avalue BETWEEN r_min AND r_max

繰り返しになりますが、範囲を範囲の文字列リストとしてテーブルに格納した短い答えに戻ると、検索ごとにそのタイプの文字列操作を行うのは実用的ではありません。

これらの r_min 値と r_max 値のそれぞれを持つ別々の行を持つ事前設定されたテーブルを使用すると、MySQL で検索を実行できます。

于 2013-01-29T15:47:39.467 に答える