Frage

Bei einer Funktion zipdistanz (Zipfrom, Zipto), die den Abstand (in Meilen) zwischen zwei Postleitzahlen und den folgenden Tabellen berechnet:

create table zips_required(
   zip varchar2(5)
);

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

Wie kann ich eine Abfrage erstellen, die zu mir jede Postleitzahl aus der Tabelle Zips_Required zurückkehrt, und die minimale Entfernung, die eine Summe erzeugt (Standorte)> = n.

Bis jetzt haben wir gerade eine erschöpfende Schlaufe -Abfrage für jeden Radius durchgeführt, bis wir die Kriterien erfüllt haben.

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

Dies kann eine Weile auf einer großen Liste dauern. Es fühlt sich so an, als könnte dies mit einer Oracle Analytic -Abfrage in der Reihe von: gemacht werden:

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

Die einzigen analytischen Abfragen, die ich durchgeführt habe, waren "row_number Over (Partition by Order by)", und ich trete damit in unbekannte Bereiche. Jede Anleitung dazu wird sehr geschätzt.

War es hilfreich?

Lösung

Das habe ich mir ausgedacht:

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. Für jeden zip_required Berechnen Sie den Abstand zum zip_available und sortieren Sie sie nach Entfernung
  2. Für jeden zip_required das count mit range ermöglicht es Ihnen zu wissen, wie viele zip_availables sind im Radius dieser Entfernung.
  3. Filter (zuerst, wo Graf (Standorte)> n)

Ich habe Beispieldaten erstellt:

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

Notiz: Sie haben Count (Standorte) und Summe (Standorte) in Ihrer Frage verwendet.

Andere Tipps

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

Für jeden zip_required, Dies wählt die minimale Entfernung aus, in die passen N zip_available's oder maximale Entfernung, wenn die Anzahl von zip_available'S ist weniger als N.

Ich habe das gleiche Problem gelöst, indem ich eine Teilmenge von ZIPs innerhalb eines quadratischen Radius aus dem gegebenen Reißverschluss (Easy Math: <oder> NSWE -Radius) erstellte und dann jeden Eintrag in der Teilmenge durch Iterien durchführte, um festzustellen, ob es sich innerhalb des benötigten Radius befand. Arbeitete wie ein Zauber und war sehr schnell.

Ich hatte teilweise ähnliche Anforderungen in einem meiner alten Projekte ... um den Abstand zwischen 2 Zipcodes in den USA zu berechnen. Um das Gleiche zu lösen, hatte ich uns räumliche Daten sehr verwendet. Grundsätzlich bestand der Ansatz darin, den Quell -Zipcode (Breitengrad, Längengrad) und Zielzipcode (Breitengrad, Länge) zu erhalten. Jetzt hatte ich eine Funktion angewendet, um die Entfernung basierend auf dem oben genannten zu erhalten. Die Basisformel, die bei dieser Berechnung hilft, ist in der verfügbar folgende SeiteIch hatte das Ergebnis auch validiert, indem ich mich auf den Hinweis auf Diese Seite...

Hinweis: Dies liefert jedoch ungefähre Entfernungen, sodass man dies entsprechend verwenden kann. Die Vorteile werden einmal erstellt, um die Ergebnisse zu erzielen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top