/ Forside / Teknologi / Udvikling / SQL / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
[MySQL] Hvorfor findes der ikke en NEARERS~
Fra : Jekka


Dato : 12-12-03 10:19

Jeg har nogle poster i min MySQL database:

A B
3,9912 9,0121
3,7212 6,7123
7,7126 8,1772

Hvis jeg så skal finde den linie, som kommer nærmest "A=4,0122, B=7,3212"
(det er jo så række 2) - hvordan kan dét gøres?

Jeg har overvejet lidt men kan alligevel ikke helt se hvordan (betweens..
round m.v.).
Det skal siges, at der er flere millioner records i den tabel, så jeg kan
ikke bare trække alle ud og så viderebehandle i PHP (og det er i forvejen
ikke verdens hurtigste maskine jeg har)



 
 
Troels Arvin (12-12-2003)
Kommentar
Fra : Troels Arvin


Dato : 12-12-03 10:39

On Fri, 12 Dec 2003 10:18:47 +0100, Jekka wrote:

> Jeg har nogle poster i min MySQL database:
[...]

Har du overvejet om en mere avanceret database kunne være relevant for
din ret avancerede problemstilling? MySQL har godtnok nogle
GIS/geometri-agtige features under udvikling, der måske kunne være
interessante for dig, men ifølge[1] er PostgreSQL p.t. det bedste valg
til den slags, i hvertfald hvis man sammenligner PostgreSQL, DB2 og MySQL.

Hvis PostgreSQL's indbyggede geometry-typer[2] og -funktioner[3] ikke er
tilstrækkelige, kan PostgreSQL udvides med "PostGIS"[4].


Noter:
1:
"Report on Cross Matching Catalogues",
http://wiki.astrogrid.org/pub/Astrogrid/DataFederationandDataMining/cross.htm

2:
http://www.postgresql.org/docs/current/static/datatype-geometric.html

3:
http://www.postgresql.org/docs/current/static/functions-geometry.html

4:
PostGIS: http://postgis.refractions.net/

--
Greetings from Troels Arvin, Copenhagen, Denmark


Jesper Krogh (12-12-2003)
Kommentar
Fra : Jesper Krogh


Dato : 12-12-03 10:40

I dk.edb.database, skrev Jekka:
> Jeg har nogle poster i min MySQL database:
>
> A B
> 3,9912 9,0121
> 3,7212 6,7123
> 7,7126 8,1772
>
> Hvis jeg så skal finde den linie, som kommer nærmest "A=4,0122, B=7,3212"
> (det er jo så række 2) - hvordan kan dét gøres?

mysql> describe test;
+-------+-------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------+------+-----+---------+-------+
| a | float | YES | | NULL | |
| b | float | YES | | NULL | |
+-------+-------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from test;
+--------+--------+
| a | b |
+--------+--------+
| 3.9912 | 9.0121 |
| 3.7212 | 6.7123 |
| 7.7126 | 9.1772 |
+--------+--------+
3 rows in set (0.00 sec)

mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order by diff li
mit 1;
+--------+--------+------------------+
| a | b | diff |
+--------+--------+------------------+
| 3.7212 | 6.7123 | 0.90000018692017 |
+--------+--------+------------------+
1 row in set (0.00 sec)

mysql>

Sådan noget?


--
../Jesper Krogh, jesper@krogh.cc
Jabber ID: jesper@jabbernet.dk
Tøm din hjerne for Linuxviden på http://www.linuxwiki.dk


Thorbjørn Ravn Ander~ (12-12-2003)
Kommentar
Fra : Thorbjørn Ravn Ander~


Dato : 12-12-03 13:00

Jesper Krogh wrote:

> mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order by diff li

Her skal man så overveje hvordan "tættest" beregnes for flere variable.
Denne er nok nemmest at beregne.
--
Thorbjoern Ravn Andersen "...plus...Tubular Bells!"


Jekka (12-12-2003)
Kommentar
Fra : Jekka


Dato : 12-12-03 13:39

> mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order by
diff li
> mit 1;
> +--------+--------+------------------+
> | a | b | diff |
> +--------+--------+------------------+
> | 3.7212 | 6.7123 | 0.90000018692017 |
> +--------+--------+------------------+
>
> Sådan noget?

Nå, dét kan man da kalde et forståeligt eksempel! Ja, lige præcist sådan
noget (det virker). Det er dog bare lidt sløvt, når der nu er flere
millioner records i tabellen, men det kan vel ikke optimeres yderligere?
Helt konkret skal jeg bruge det til at søge i Kort og Matrikelstrelsens
database over adresser (ud fra længde-/breddegrad). Og dér er altså cirka
2,5mio. records



Thorbjørn Ravn Ander~ (15-12-2003)
Kommentar
Fra : Thorbjørn Ravn Ander~


Dato : 15-12-03 12:03

Jekka wrote:

> Helt konkret skal jeg bruge det til at søge i Kort og Matrikelstrelsens
> database over adresser (ud fra længde-/breddegrad). Og dér er altså cirka
> 2,5mio. records

Så var det måske en ide at hitte på en måde så du kun kigger på det
landeområde i "nærheden" af hvor du er?

--
Thorbjoern Ravn Andersen "...plus...Tubular Bells!"


Peter Brodersen (12-12-2003)
Kommentar
Fra : Peter Brodersen


Dato : 12-12-03 14:32

On Fri, 12 Dec 2003 10:40:09 +0100, Jesper Krogh <jesper@krogh.cc>
wrote:

>mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order by diff li
>mit 1;

Ehm, hvis vi har punktet 1,1 - så vil dit eksempel mene, at 2,2 og 3,1
er lige langt fra 1,1? Det er jo ikke tilfældet.

Du skal indbygge pythagoras. Det burde dog være en snild sag.

--
- Peter Brodersen

Ugens sprogtip: jamen (og ikke jammen)

Jesper Krogh (12-12-2003)
Kommentar
Fra : Jesper Krogh


Dato : 12-12-03 14:35

I dk.edb.database, skrev Peter Brodersen:
> On Fri, 12 Dec 2003 10:40:09 +0100, Jesper Krogh <jesper@krogh.cc>
> wrote:
>
> >mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order by diff li
> >mit 1;
>
> Ehm, hvis vi har punktet 1,1 - så vil dit eksempel mene, at 2,2 og 3,1
> er lige langt fra 1,1? Det er jo ikke tilfældet.
>
> Du skal indbygge pythagoras. Det burde dog være en snild sag.

Det medgiver jeg.. nu gik første spørgsmål dog ikke på at det var et
koordinatsæt der blev regnet på. Og "nærmest" var ikke defineret..

--
../Jesper Krogh, jesper@krogh.cc
Jabber ID: jesper@jabbernet.dk
Tøm din hjerne for Linuxviden på http://www.linuxwiki.dk


Jekka (12-12-2003)
Kommentar
Fra : Jekka


Dato : 12-12-03 15:34

> >mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order by
diff li
> >mit 1;
>
> Ehm, hvis vi har punktet 1,1 - så vil dit eksempel mene, at 2,2 og 3,1
> er lige langt fra 1,1? Det er jo ikke tilfældet.
>
> Du skal indbygge pythagoras. Det burde dog være en snild sag.

Og for dem som ikke mener "det burde være en snild sag"? Det er noget
med længde^2 * bredde^2 og så ét eller andet ... ?



Jesper Krogh (12-12-2003)
Kommentar
Fra : Jesper Krogh


Dato : 12-12-03 15:39

I dk.edb.database, skrev Jekka:
> > >mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order by
> diff li
> > >mit 1;
> >
> > Ehm, hvis vi har punktet 1,1 - så vil dit eksempel mene, at 2,2 og 3,1
> > er lige langt fra 1,1? Det er jo ikke tilfældet.
> >
> > Du skal indbygge pythagoras. Det burde dog være en snild sag.
>
> Og for dem som ikke mener "det burde være en snild sag"? Det er noget
> med længde^2 * bredde^2 og så ét eller andet ... ?

Og til dette job, kan man endda droppe "ét eller andet" og nøjes med det
første.

--
../Jesper Krogh, jesper@krogh.cc
Jabber ID: jesper@jabbernet.dk
Tøm din hjerne for Linuxviden på http://www.linuxwiki.dk


Jekka (12-12-2003)
Kommentar
Fra : Jekka


Dato : 12-12-03 15:54

> > > >mysql> select a,b,ABS(a-4.0122)+ABS(b-7.3213) as diff from test order
by
> > diff li
> > > >mit 1;
> > >
> > > Ehm, hvis vi har punktet 1,1 - så vil dit eksempel mene, at 2,2 og 3,1
> > > er lige langt fra 1,1? Det er jo ikke tilfældet.
> > >
> > > Du skal indbygge pythagoras. Det burde dog være en snild sag.
> >
> > Og for dem som ikke mener "det burde være en snild sag"? Det er
noget
> > med længde^2 * bredde^2 og så ét eller andet ... ?
>
> Og til dette job, kan man endda droppe "ét eller andet" og nøjes med det
> første.

Dvs. "select a,b,ABS(a-(4.0122*4.0122))+ABS(b-(7.3213*7.3213)) as diff from
test order by diff" ? Skulle det give den store forskel? Jeg mener.. det gør
jo bare, at der bliver forholdsvis mere forskel på dem, men det ændre vel
ikke resultatet?

Output tidligere:
[2, 3.7212, 6.7123, 2.9910998344421]
[3, 7.7126, 9.1772, 4.8898005485535]
[1, 3.9912, 9.0121, 5.0209002494812]

Output nu:
[2, 3.7212, 6.7123, 65.840299129486]
[3, 7.7126, 9.1772, 74.173401355743]
[1, 3.9912, 9.0121, 77.069301128387]



Jesper Krogh (12-12-2003)
Kommentar
Fra : Jesper Krogh


Dato : 12-12-03 16:19

I dk.edb.database, skrev Jekka:
> > > Og for dem som ikke mener "det burde være en snild sag"? Det er
> noget
> > > med længde^2 * bredde^2 og så ét eller andet ... ?
> >
> > Og til dette job, kan man endda droppe "ét eller andet" og nøjes med det
> > første.
>
> Dvs. "select a,b,ABS(a-(4.0122*4.0122))+ABS(b-(7.3213*7.3213)) as diff from
> test order by diff" ? Skulle det give den store forskel? Jeg mener.. det gør
> jo bare, at der bliver forholdsvis mere forskel på dem, men det ændre vel
> ikke resultatet?

Det var forkert..

Det er hele den ABS() du skal gange med sig selv.

--
../Jesper Krogh, jesper@krogh.cc
Jabber ID: jesper@jabbernet.dk
Tøm din hjerne for Linuxviden på http://www.linuxwiki.dk


Jekka (12-12-2003)
Kommentar
Fra : Jekka


Dato : 12-12-03 17:20

> > Dvs. "select a,b,ABS(a-(4.0122*4.0122))+ABS(b-(7.3213*7.3213)) as diff
from
> > test order by diff" ? Skulle det give den store forskel? Jeg mener..
det gør
> > jo bare, at der bliver forholdsvis mere forskel på dem, men det ændre
vel
> > ikke resultatet?
>
> Det var forkert..
> Det er hele den ABS() du skal gange med sig selv.

a = 4.0122
b = 7.3213

select a, b,
(ABS(a-4.0122)*ABS(a-4.0122))+(ABS(b-7.3213)*ABS(b-7.3213)) as diff
from test order by diff

[2, 3.7212, 6.7123, 0.45556222087558]
[1, 3.9912, 9.0121, 2.8592463842771]
[3, 7.7126, 9.1772, 17.137327858909]

Tjaa.. der er jo lidt mere forskel på det end "originalt", så det er jo nok
godt nok. Resultatet ser da fint ud.

Men mht. process tiden - hvad er det smarteste mon.. at trække de 2,5 mio.
records ud af databasen og ind i PHP (og så arbejde videre med det dérfra)
eller finde en anden "formel" til SQL'en?



Kim Hansen (12-12-2003)
Kommentar
Fra : Kim Hansen


Dato : 12-12-03 17:43

"Jekka" <a@b.cde> writes:

> Dvs. "select a,b,ABS(a-(4.0122*4.0122))+ABS(b-(7.3213*7.3213)) as diff from
> test order by diff" ? Skulle det give den store forskel? Jeg mener.. det gør
> jo bare, at der bliver forholdsvis mere forskel på dem, men det ændre vel
> ikke resultatet?

SELECT a,b,pow(a-4.0122,2)+pow(b-7.3213,2) as diff ...

Måske er det hurtigere at bruge (a-4.0122)*(a-4.0122) i stedet for
pow(), det må du finde d af ved at teste.

Men det er sikkert endnu bedre at skifte til postgresql, den database
har en masse special-funktioner der er lavet til dette.

--
Kim Hansen | |\ _,,,---,,_ | Det er ikke
Dalslandsgade 8, A708 | /,`.-´` -. ;:-. | Jeopardy.
2300 København S | |,4- ) )-,_. ,\ ( `'-' | Svar _efter_
Tlf: 32 88 60 86 | '---''(_/--' `-'\_) | spørgsmålet.

Peter Brodersen (12-12-2003)
Kommentar
Fra : Peter Brodersen


Dato : 12-12-03 18:10

On Fri, 12 Dec 2003 15:38:37 +0100, Jesper Krogh <jesper@krogh.cc>
wrote:

>> Og for dem som ikke mener "det burde være en snild sag"? Det er noget
>> med længde^2 * bredde^2 og så ét eller andet ... ?
>Og til dette job, kan man endda droppe "ét eller andet" og nøjes med det
>første.

Pythagoras er a^2 + b^2 = c^2. Det er ikke heldigt at gange, for hvis
bredden er lig 0, så vil (længde^2 * bredde^2) også lig med 0 :)

Så det må blive noget i stil med:

SQRT(POW((a-4.0122),2)+POW((b-7.3213),2))

Jeg har udeladt ABS(), da det her vil give samme resultat. I
princippet kan man også udelade SQRT(), hvis man ikke vil have
afstanden ud, men blot bruger feltet til at sortere efter.

--
- Peter Brodersen

Ugens sprogtip: jamen (og ikke jammen)

Søg
Reklame
Statistik
Spørgsmål : 177500
Tips : 31968
Nyheder : 719565
Indlæg : 6408518
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste