Avatar billede andreas Nybegynder
13. maj 2008 - 12:29 Der er 20 kommentarer og
1 løsning

Beregne afstande mellem punkter

Jeg har nedstående tabel, hvori jeg gemmer positionen for et "tag" når folk bevæger sig rundt i et lokale. Jeg skal nu have fundet ud af, om et bestemt tag (defineret ud fra deres ID, etc 2341) har været tættere på hianden end etc 30 meter. Værdierne i tabellen er opgivet i meter. Formlen for, at finde afstanden er: distance = sqrt ( (x1-x2)^2 + (y1-y2)^b )

Jeg bliver derfor nødt til at lave en form for temp tabel der viser afstanden fra 2341's positioner og til alle de andre tags positioner, SÅ længe afstanden er etc 30 eller mindre.

Tabel design:

time  | tag_id | positionX | positionY |
---------------------------------------|
11-08 | 2341  |    10    |    40    |
---------------------------------------|
11-08 | 2341  |    11    |    42    |
---------------------------------------|
11-08 | 2341  |    14    |    45    |
---------------------------------------|
11-08 | 2542  |    12    |    42    |
---------------------------------------|
11-08 | 2542  |    12    |    32    |
---------------------------------------|
11-08 | 2542  |    11    |    37    |
---------------------------------------|
11-08 | 2542  |    10    |    38    |
---------------------------------------|
Avatar billede pgroen Nybegynder
13. maj 2008 - 13:09 #1
Hvorfor besvære sig med en temp-tabel?

SELECT DISTINCT t1.tag_id
          FROM test_table t1, test_table t2
          WHERE SQRT (  (  (t1.positionX - t2.positionX)
                        * (t1.positionX - t2.positionX))
                      + (  (t1.positionY - t2.positionY)
                        * (t1.positionY - t2.positionY))) < 30
            AND t2.tag_id = 2341;


Eller alternativt:



SELECT DISTINCT t1.tag_id
          FROM test_table t1, test_table t2
          WHERE  (  (t1.positionX - t2.positionX)
                  * (t1.positionX - t2.positionX))
                + (  (t1.positionY - t2.positionY)
                  * (t1.positionY - t2.positionY)) < 30 * 30
            AND t2.tag_id = 2341;
Avatar billede andreas Nybegynder
13. maj 2008 - 13:23 #2
Doh ja, jeg var næsten nået frem til det samme ;) Jeg teser det lige senere.

jeg forsøger bare lige at lure dit alternativ, hvordan det lige hænger sammen med, at du ganger 30 på ? ;p
Avatar billede andreas Nybegynder
13. maj 2008 - 13:26 #3
Åh, du har fjernet kvadratroden... men til hvilken fordel? Er der en væsentlig forbedring i hastigheden eller?
Avatar billede pgroen Nybegynder
13. maj 2008 - 13:31 #4
I praksis giver det nok ikke den store forskel, men jo, 30*30 betragtes af compileren som en konstant, og er meget hurtigere at beregne, end kvadratroden af noget variabelt...

Og det samme gælder "x*x" versus "power(2,x)"
-Afhængigt af hvor smart compileren er.
Avatar billede andreas Nybegynder
13. maj 2008 - 13:56 #5
Jeg tror det gør forskel for os. Vi har 1000 tags der logger deres position hvert halve sekund :) Så jo hurtigere det kan gøres, jo bedre :)
Avatar billede pgroen Nybegynder
13. maj 2008 - 14:34 #6
Så altså ca. 200 mio rækker i døgnet ???
- Jeg tror I får performance-problemer...

(Men det er jo en helt anden snak ;-)
Avatar billede jogii Nybegynder
13. maj 2008 - 14:40 #7
Jeg er bare nysgerrig. Spiller tiden ingen rolle i dine beregninger? Så det er ikke den samtidige afstand du er interesseret i?
Avatar billede andreas Nybegynder
13. maj 2008 - 15:19 #8
pgroen - ja det er et interessant forsøg vi har gang i :)

jogii - jo du ku godt ha ret i, at de to tags etc skal ha mødt hinanden inden for en tidsramme der hedder 30 minutter... men det er vel at indsætte en t2.time - t1.time < 30
eller sådan?
Avatar billede pgroen Nybegynder
13. maj 2008 - 17:52 #9
Andreas,

Jogiis bemærkning om tidsrammen er måske det der redder jeres respons-tid, hvis I sørger for at have de rette indexer på plads.

Men hvis det viser sig at Jeres applikation performer helt ad hekkenfelt til, så kunne det måske være en ide at overveje den nye spatial-funktionalitet i SQLserver 2008
(se: http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx)

Jeg har i øvrigt ikke specielt meget forstand på SQLserver; er mere Oracle-mand...
Avatar billede janus_007 Nybegynder
13. maj 2008 - 19:09 #10
Bruger du SQL2005?
Avatar billede andreas Nybegynder
14. maj 2008 - 08:46 #11
pgroen, Enig jeg havde helt glemt det med tidsrammen og jeg er også spændt på hvordan det kommer til at performe. Det vi har gang i her er et forsøg på universitetet med lokalisering af personer og herefter finde ud af hvem der har været i "kontakt" med hvem. Jeg vil lige kigge på den nye funktionalitet der, og se om den er brugbar for os. Jeg er heller ikke den store fan af MS SQL, men den er blevet pålagt. Jeg er også mere til Oracle og MySQL (til de mindre ting)

Janus, ja pt bruger vi 2005.
Avatar billede andreas Nybegynder
14. maj 2008 - 11:15 #12
Pt, anvender vi følgende query:

SELECT DISTINCT t1.tag_id, t1.time
FROM TAGdata t1, TAGdata t2

WHERE
( (t1.positionX - t2.positionX) * (t1.positionX - t2.positionX)) +
( (t1.positionY - t2.positionY) * (t1.positionY - t2.positionY)) < 30 *30
AND t2.tag_id = 2341
AND t1.tag_id != 2341
AND t1.time < '2008-05-13 13:37'
AND t1.time > '2008-05-13 13:34'
AND t2.time < '2008-05-13 13:37'
AND t2.time > '2008-05-13 13:34'


Nogle der har nogle gode invendinger til dette? Ud fra dette får jeg at vide hvilket tag 2341 har været inden for afstanden, på hvilke tidspunkter. Korrekt?
Avatar billede andreas Nybegynder
14. maj 2008 - 11:17 #13
Jeg glemte lige at nævne, at jeg har tilføjet en t1.tag_id != 2341 efter som det tag man søger på ikke har været i nærheden af sig selv?
Avatar billede pgroen Nybegynder
14. maj 2008 - 11:30 #14
Det ser såmænd rigtig nok ud, bortset fra at når du har t1.time med i din DISTINCT select får du ca. 700 forekomster pr. tag, forudsat at du logger hvert halve sekund, og at personerne i øvrigt står stille i den givne 3-minutters periode...
Avatar billede andreas Nybegynder
14. maj 2008 - 11:37 #15
Hmmm, det har du selvfølgelig ret i. Men hvis jeg nu formatter time til kun at vise minutter, vil disse forekomster så ikke reduceres?
Avatar billede pgroen Nybegynder
14. maj 2008 - 11:52 #16
Hov, din 'time' kolonne er forhåbentlig ikke en tekst ?
Avatar billede andreas Nybegynder
14. maj 2008 - 12:21 #17
Nej, den er af typen datetime.
Avatar billede andreas Nybegynder
14. maj 2008 - 12:38 #18
SELECT DISTINCT

t1.tag_id,
DATE_FORMAT(t1.time,'%Y-%m-%d %k:%i')

FROM TAGdata t1, TAGdata t2

WHERE
( (t1.positionX - t2.positionX) * (t1.positionX - t2.positionX)) +
( (t1.positionY - t2.positionY) * (t1.positionY - t2.positionY)) < 3 * 3

AND t2.tag_id = 2341
AND t1.tag_id != 2341

AND t1.time < '2008-05-13 13:37'
AND t1.time > '2008-05-13 13:34'
AND t2.time < '2008-05-13 13:37'
AND t2.time > '2008-05-13 13:34'

Jeg har nu tilføjet en DATE_FORMAT som gør, at der ikke vises resultater for sekunder, men kun i minutter. Nogle indvendinger?
Avatar billede janus_007 Nybegynder
14. maj 2008 - 20:06 #19
Nu uden jeg vil blande mig yderligere... men umiddelbart så ligner det en oplagt sag at klare i CLR.
Avatar billede andreas Nybegynder
14. maj 2008 - 20:59 #20
Du må meget gerne komme ind på det janus, i CLR.. ;)
Avatar billede janus_007 Nybegynder
15. maj 2008 - 19:24 #21
uha.. hehe.. det må blive når jeg finder lidt tid :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester