2009-06-23 15 views
6

2つの郵便番号と以下の表の間の関数zipdistance(マイル)の距離を算出する(zipfrom、zipto)を考える:Oracleの分析質問

create table zips_required(
    zip varchar2(5) 
); 

create table zips_available(
    zip varchar2(5), 
    locations number(100) 
); 
私は私に戻りますクエリを作成するにはどうすればよい

zips_requiredテーブルの各郵便番号と合計(場所)> = nを生成する最小距離。

これまでは、条件を満たすまで、各半径について徹底的なクエリを実行しました。

--Do this over and over incrementing the radius until the minimum requirement is met 
select count(locations) 
from zips_required zr 
left join zips_available za on (zipdistance(zr.zip,za.zip)< 2) -- Where 2 is the radius 

これは、大きなリストではしばらく時間がかかります。これは、の線に沿ってオラクルの分析クエリを行うことができるようにそれは感じている:私がされている行っている

min() over (
    partition by zips_required.zip 
    order by zipdistance(zips_required.zip, zips_available.zip) 
    --range stuff here? 
) 

のみ分析クエリベース「(で順序でパーティション)を超えるROW_NUMBER」、そして私は踏みよこれで未知の領域に入る。これに関するガイダンスは大変ありがとうございます。各zip_requiredに対して

答えて

2

これは私が思いついたものです:各zip_requiredについて

SELECT zr, min_distance 
    FROM (SELECT zr, min_distance, cnt, 
       row_number() over(PARTITION BY zr ORDER BY min_distance) rnk 
      FROM (SELECT zr.zip zr, zipdistance(zr.zip, za.zip) min_distance, 
         COUNT(za.locations) over(
          PARTITION BY zr.zip 
          ORDER BY zipdistance(zr.zip, za.zip) 
         ) cnt 
        FROM zips_required zr 
        CROSS JOIN zips_available za) 
      WHERE cnt >= :N) 
WHERE rnk = 1 
  1. zip_availableまでの距離を算出し、各zip_requiredについて距離
  2. によってそれらを並べ替えるcountrangeと、あなたはどのように知ることができます多くの場合zip_availablesはその距離の半径にあります。
  3. フィルタ(最初のCOUNT(場所)> N)

私は、サンプルデータを作成するために使用される:

INSERT INTO zips_required 
    SELECT to_char(10000 + 100 * ROWNUM) FROM dual CONNECT BY LEVEL <= 5; 

INSERT INTO zips_available 
    (SELECT to_number(zip) + 10 * r, 100 - 10 * r FROM zips_required, (SELECT ROWNUM r FROM dual CONNECT BY LEVEL <= 9)); 

CREATE OR REPLACE FUNCTION zipdistance(zipfrom VARCHAR2,zipto VARCHAR2) RETURN NUMBER IS 
BEGIN 
    RETURN abs(to_number(zipfrom) - to_number(zipto)); 
END zipdistance; 
/

注:あなたにCOUNT(場所)とSUM(場所)を使用します質問、私はそれがCOUNT(場所)であったと仮定

1
SELECT * 
FROM (
     SELECT zip, zd, ROW_NUMBER() OVER (PARTITION BY zip ORDER BY rn DESC) AS rn2 
     FROM (
       SELECT zip, zd, ROW_NUMBER() OVER (PARTITION BY zip ORDER BY zd DESC) AS rn 
       FROM (
         SELECT zr.zip, zipdistance(zr.zip, za.zip) AS zd 
         FROM zips_required zr 
         JOIN zips_available za 
         ) 
       ) 
     WHERE rn <= n 
     ) 
WHERE rn2 = 1 

、これはS N未満であるNzip_available「がzip_availableの数があれば、S、または最大の距離を」収まるに最小距離を選択します。

+0

これは近いと思います。あなたの例では、rnはちょうど距離で順序付けられた2つのジップの間の距離のランキングになります。私が必要とするのは、そのリスト内の最後のもののzipdistanceで、その場所の合計と以前のすべての場所がN以上です。 –

+0

@Josh:これは最も近いN個の場所の距離を返します。あなたは何をしたいですか? – Quassnoi

+0

Oracleクエリーで1を制限しますか?私は何かを逃した。 – tuinstoel

1

Iは、所与のジップから自乗半径内のZIPのサブセットを作成することにより、同じ問題を解決する:次に、(簡単な数学<又は> NSWE半径)iteratin gが必要な半径内にあるかどうかを確認します。魅力のように働き、とても速かった。

0

私は、私の古いプロジェクトの1つに、似たような要件がありました。米国の2つの郵便番号間の距離を計算しました。これを解決するために、私はUS Spatial Dataを大いに活用しました。基本的には、ソース郵便番号(緯度、経度)と目的地郵便番号(緯度、経度)を取得する方法でした。 今度は、上記に基づいて距離を取得する関数を適用しました。 1はそれに応じてこれを使用することができますので、しかし、これは、おおよその距離を提供します。この計算を行う際に役立ちますベース式は

注... following site私もthis siteを参照して結果を検証していた で利用可能です。メリットは一度成果を出すために超高速に構築されます。