2017-01-18 1 views
4

Geordnetes Ziel: Alle Postleitzahlen innerhalb von 30 Meilen von einem bestimmten Reißverschluss.Haversine Formeleinheit Fehler - PL/SQL

Datenquelle: Liste der Postleitzahlen, mit Breite und Länge als 'x' & 'y'.

Beispiel:

create or replace view zips as 
select 37171 zip, 36.362704 y, -87.30434 x,'Southside' City, 'TN' State from dual 
union 
select 37212, 36.133012, -86.802764, 'Nashville', 'TN' from dual 
union 
select 37027, 36.00245, -86.791159, 'Brentwood', 'TN' from dual 
union 
select 37191, 36.501196, -87.539057, 'Woodlawn', 'TN' from dual 
union 
select 37067, 35.928406, -86.805538, 'Franklin', 'TN' from dual ; 

Was ich versucht: Ich habe etwas gefunden, der aussah, wollte solve all my problems:

CREATE OR REPLACE FUNCTION distance (Lat1 IN NUMBER, 
            Lon1 IN NUMBER, 
            Lat2 IN NUMBER, 
            Lon2 IN NUMBER, 
            Radius IN NUMBER DEFAULT 3963) RETURN NUMBER IS 
-- Convert degrees to radians 
DegToRad NUMBER := 57.29577951; 

BEGIN 
    RETURN(NVL(Radius,0) * ACOS((sin(NVL(Lat1,0)/DegToRad) * SIN(NVL(Lat2,0)/DegToRad)) + 
     (COS(NVL(Lat1,0)/DegToRad) * COS(NVL(Lat2,0)/DegToRad) * 
     COS(NVL(Lon2,0)/DegToRad - NVL(Lon1,0)/ DegToRad)))); 
END; 

aber es gab mir funkigen Nummern - konsequent zu klein (ich weiß, es ist nicht mehr als 1 Meile von Franklin nach Nashville), aber nicht mit einem konstanten Faktor, den ich feststellen kann. (Code I zu Test verwendet wird, ist unten - ich gerade im Vergleich Entfernungen auf Google Maps mit diesen Abständen)

select b.zip 
    ,b.city 
    ,b.state 
    ,distance(a.x,a.y,b.x,b.y) distance 
from zips a, zips b 
where a.zip=37067 
order by distance; 

Also, ich dachte, vielleicht die Geodaten Gruppe eine andere Art und Weise der Aufzeichnung lat & lang hatte und ich fand Wikipedia's Haversine formula und gedreht das in eine Funktion

Gleiches Problem - Ergebnisse sind fast genau die gleichen, die mich fragen, was das Problem ist. Welche Transformation mache ich nicht? Was vermisse ich?

Beachten Sie, dass ich froh wäre, eine flache Erde anzunehmen und pythagoreische Entfernungen zu verwenden, da ich nur 30-50 Meilen für jeden Satz von Postleitzahlen betrachte, den ich betrachte, aber ich müsste herausfinden Was ist mit meiner Breiten-/Längengrad-Umwandlung?

+1

Ein großer erster IMHO Beitrag. Rechte Tags, Datenmuster, Code- und Datenformatierung, Referenzen, ... Willkommen bei SO! – Aleksej

Antwort

2

Sieht aus wie ein Parameter Problem. Der Header ist:

CREATE OR REPLACE FUNCTION distance (Lat1 IN NUMBER, 
            Lon1 IN NUMBER, 
            Lat2 IN NUMBER, 
            Lon2 IN NUMBER, 

Und Sie nennen es wie folgt:

distance(a.x,a.y,b.x,b.y) 

Aber Ihre Ansicht ist:

create or replace view zips as 
select 37171 zip, 36.362704 y, -87.30434 x,'Southside' City, 'TN' State from dual 
union 
select 37212, 36.133012, -86.802764, 'Nashville', 'TN' from dual 
union 
select 37027, 36.00245, -86.791159, 'Brentwood', 'TN' from dual 
union 
select 37191, 36.501196, -87.539057, 'Woodlawn', 'TN' from dual 
union 
select 37067, 35.928406, -86.805538, 'Franklin', 'TN' from dual ; 

Nach der Ansicht, x ist die Länge und y ist der Breitengrad. So ist der Funktionsaufruf sollte sein:

distance(a.y,a.x,b.y,b.x) 

Alternativ können Sie das „x“ tauschen und „y“ Aliase in der Ansicht und lassen alles andere als ist.

+1

Ich höre es ist gut, die Stirn mit der Handfläche hin und wieder zu schlagen. Schüttelt die Dinge. Danke, dass du mir die Gelegenheit dazu gegeben hast. – Maggie

+0

@Maggie, kein Problem. Ich fühle den gleichen Weg und wahrscheinlich eine Delle in meinem Schädel von Jahren des Vergessens Semikolon, etc. – tilper

+0

Eine wichtige Lektion im Wert von anständigen Namen. Sie hätten dies wahrscheinlich sofort bemerkt, wenn die Ansichtsspalten "Länge" und "Breite" statt "x" und "y" gewesen wären. – APC