2009-06-23 184 views
6

給定兩個郵政編碼和下面的表之間的函數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 

這可能需要一段時間在一個大的列表中。這感覺就像這可能是與沿行的Oracle分析查詢來完成:我已經做了一直

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

唯一的分析查詢基於「(由順序分區)ROW_NUMBER過」,而我踩着用這個進入未知區域。任何關於此的指導都非常感謝。

回答

2

這是我想出了:

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_required計算距離爲zip_available和距離
  2. 對於每個zip_requiredcountrange排序他們讓你知道如何許多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 

對於每個zip_required,這將選擇的最小距離成適合Nzip_available的,或最大距離如果zip_available數量的小於N

+0

我覺得這很接近。在你的例子中,rn只是按距離排序的兩個拉鍊之間的距離的排名。我需要的是該列表中最後一個的zip距離,它的位置總和加上所有先前的位置總和大於或等於N. – 2009-06-23 17:10:59

1

我解決了同樣的問題,從給定的zip(簡單的數學:<或> NSWE半徑)在方形半徑內創建一個ZIP的子集,然後iteratin g通過子集中的每個條目查看它是否在所需半徑內。像魅力一樣工作,速度非常快。

0

我在其中一箇舊項目中有部分相似的要求...計算美國2個郵編碼之間的距離。爲了解決這個問題,我使用了美國空間數據。基本上,這個方法是獲取Source Zipcode(經度,緯度)和目標郵政編碼(經度,緯度)。 現在我已經應用了一個函數來獲得基於上述距離。基本配方,幫助在做這個計算可在following site 我也參照this site驗證結果...

注:然而,這將提供近似距離,因此可以相應地使用這個。福利一旦建成超快取得結果。