Oracle 分析に関する質問
-
06-07-2019 - |
質問
2 つの郵便番号間の距離 (マイル単位) を計算する関数 zip distance(zipfrom,zipto) と次のテーブルを指定します。
create table zips_required(
zip varchar2(5)
);
create table zips_available(
zip varchar2(5),
locations number(100)
);
zips_required テーブルから各郵便番号と、sum(locations) >= 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
リストが大きい場合、これには時間がかかる場合があります。これは、次のような Oracle 分析クエリで実行できるように感じます。
min() over (
partition by zips_required.zip
order by zipdistance( zips_required.zip, zips_available.zip)
--range stuff here?
)
私が行った唯一の分析クエリは「row_number over (partition by order by)」ベースであり、これで未知の領域に足を踏み入れています。これに関するご指導をいただければ幸いです。
解決
これが私が思いついたものです:
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
- 各
zip_required
についてzip_available
までの距離を計算し、距離で並べ替えます - 各
count
について、range
とzip_availables
を使用すると、その距離の半径にある<=>の数を知ることができます。 - フィルター(最初はCOUNT(locations)<!> gt; 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(locations)およびSUM(locations)を使用しましたが、COUNT(locations)であると想定しました
他のヒント
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
各zip_required
に対して、これはN
zip_available
に適合する最小距離、または<=>の数が<=>より小さい場合に最大距離を選択します。
特定のzipから半径内にZIPのサブセットを作成し(簡単な計算:<!> lt;または<!> gt; NSWE radius)、サブセットの各エントリを繰り返し処理して、同じ問題を解決しました必要な半径内にあったかどうかを確認します。魅力のように機能し、非常に高速でした。
私の古いプロジェクトの 1 つにも、部分的に同様の要件がありました。米国の 2 つの郵便番号間の距離を計算します。同じ問題を解決するために、私は米国空間データを大いに活用しました。基本的に、このアプローチは、送信元の郵便番号 (緯度、経度) と宛先の郵便番号 (緯度、経度) を取得することでした。さて、上記に基づいて距離を取得する関数を適用しました。この計算を行う際に役立つ基本式は、次の場所にあります。 次のサイト私も参照して結果を検証しました このサイト...
注記:ただし、これによりおおよその距離が得られるため、それに応じて使用できます。利点は構築されると、結果を取得するために超高速に実行されます。