2009-06-23 31 views
6

Data una funzione zipdistance (zipfrom, zipto), che calcola la distanza (in miglia) tra due codici di avviamento postale e le seguenti tabelle:Oracle Analytic Domanda

create table zips_required(
    zip varchar2(5) 
); 

create table zips_available(
    zip varchar2(5), 
    locations number(100) 
); 

Come posso creare una query che restituirà a me ogni codice zip dalla tabella zips_required e la distanza minima che produrrebbe una somma (località)> = n.

Fino ad ora abbiamo appena correre un'interrogazione ciclo completo per ogni raggio fino a quando abbiamo incontrato i criteri.

--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 

Questo può richiedere un po 'di tempo in un elenco di grandi dimensioni. Ci si sente come questo potrebbe essere fatto con una query analitica oracolo lungo le linee di:

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

Le uniche domande analitiche che ho fatto sono stati "row_number over (partizione per ordine da)" basata, e sto calpestando in aree sconosciute con questo. Qualsiasi consiglio su questo è molto apprezzato.

risposta

2

Questo è ciò che mi si avvicinò con:

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. Per ogni zip_required calcolare la distanza dal zip_available e ordinarli in base alla distanza
  2. Per ogni zip_required la count con range consente di sapere come molti sono zip_availables nel raggio di tale distanza.
  3. filtro (primo in cui COUNT (posizioni)> N)

ho usato per creare dati di esempio:

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; 
/

Nota: si è utilizzato COUNT (posizioni) e SUM (posizioni) nella vostra domanda, ho pensato che era COUNT (posizioni)

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 

Per ogni zip_required, questo selezionerà la distanza minima in cui si adattano Nzip_available 's, o la distanza massima se il numero di zip_available' s è minore di N.

+0

Penso che questo sia vicino. Nel tuo esempio, rn sarà solo la classifica della distanza tra 2 zip ordinate dalla distanza. Ciò di cui ho bisogno è la distanza zip dell'ultima in quella lista che la somma delle sue posizioni più tutte le posizioni precedenti è maggiore o uguale a N. –

+0

@Josh: questo restituirà la distanza della posizione più lontana con la N più vicina. Non è quello che vuoi? – Quassnoi

+0

limite 1 in una query Oracle? Ho perso qualcosa. – tuinstoel

1

ho risolto lo stesso problema creando un sottoinsieme di avviamento postale di un raggio piazza dalla data zip (matematica facile: < o> NSWE raggio), quindi iteratin g attraverso ogni voce nel sottoinsieme per vedere se era all'interno del raggio necessario. Ha funzionato come un fascino ed è stato molto veloce.

0

ho avuto richieste in parte simili, in uno dei miei vecchi progetti ... per calcolare la distanza tra i 2 zipcodes negli Stati Uniti. Per risolvere lo stesso ho fatto un grande uso di US Spatial Data. In sostanza l'approccio è stato quello di ottenere il CAP Fonte (latitudine, longitudine) e CAP Destinazione (latitudine, longitudine). Ora poi ho avuto applicata una funzione per ottenere la distanza in base a quanto sopra esposto. La formula di base che aiuta a fare questo calcolo è disponibile in following site Avevo anche convalidato il risultato facendo riferimento alla this site ...

Nota: Tuttavia questo fornirà distanze approssimate, così si può usare questa conseguenza. I benefici sono una volta costruiti i suoi superfast per recuperare i risultati.