Вопрос

Имеется функция 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

Это может занять некоторое время в большом списке. Такое ощущение, что это можно сделать с помощью аналитического запроса оракула по следующим направлениям:

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

Единственные аналитические запросы, которые я сделал, были " row_number over (разбить по порядку на) " основанный, и я ступаю в неизвестные области с этим. Любое руководство по этому вопросу высоко ценится.

Это было полезно?

Решение

Это то, что я придумал:

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 (location) > 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 (местоположения)

    Другие советы

    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 в квадратном радиусе от заданного почтового индекса (легкая математика: < или > радиус NSWE), затем перебирая каждую запись в подмножестве, чтобы посмотрите, был ли он в пределах необходимого радиуса. Работал как шарм и был очень быстрым.

    У меня были частично аналогичные требования в одном из моих старых проектов ... для расчета расстояния между двумя почтовыми индексами в США. Чтобы решить то же самое, я широко использовал пространственные данные США. В основном подход заключался в получении исходного почтового индекса (широта, долгота) и целевого почтового индекса (широта, долгота). Теперь я применил функцию, чтобы получить расстояние на основе вышеизложенного. Базовая формула, которая помогает выполнить этот расчет, доступна на следующем сайте . Я также подтвердил результат, сославшись на этот сайт ...

    Примечание. Однако это даст приблизительное расстояние, поэтому можно использовать его соответствующим образом. Преимущества когда-то построены так быстро, чтобы получить результаты.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top