6

给定一个函数 zipdistance(zipfrom,zipto),它计算两个邮政编码之间的距离(以英里为单位)和下表:

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 over (partition by order by)”的,我正在涉足未知领域。非常感谢对此的任何指导。

4

4 回答 4

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. 对于每个with ,您可以知道zip_required该距离的半径内有多少。countrangezip_availables
  3. 过滤器(首先是 COUNT(locations) > 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)

于 2009-06-24T07:51:56.853 回答
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,这将选择适合的最小距离,或者如果 的数量小于,则选择N zip_available最大距离。zip_availableN

于 2009-06-23T16:49:28.117 回答
1

我通过在给定 zip 的平方半径内创建 ZIP 的子集(简单数学:< 或 > NSWE 半径)解决了同样的问题,然后遍历子集中的每个条目以查看它是否在所需的半径内。像魅力一样工作,速度非常快。

于 2009-06-27T23:42:52.083 回答
0

在我的一个旧项目中,我有部分类似的要求……计算美国 2 个邮政编码之间的距离。为了解决同样的问题,我充分利用了美国空间数据。基本上,该方法是获取源邮政编码(纬度,经度)和目的地邮政编码(纬度,经度)。现在,我已经应用了一个函数来根据上述内容获取距离。有助于进行此计算的基本公式可在以下站点中找到, 我还通过引用此站点验证了结果...

注意:但是这将提供近似距离,因此可以相应地使用它。好处一旦构建,它就可以超快速地获取结果。

于 2012-08-10T18:56:40.950 回答