2010-01-09 7 views
10

Próbuję utworzyć zapytanie, ale mam pewne trudności.Typ geograficzny serwera SQL Server najbliższy punkt na linii

Mam bazę danych SQL Server 2008 z tabelą, która zawiera, oprócz innych pól, pole geograficzne, które opisuje segmenty drogi. (Te dane zostały zaimportowane z danych TIGER/Line ze spisu powszechnego USA.)

Mam inny stały punkt opisujący lokalizację użytkownika. Chcę znaleźć najbliższy segment drogi w bazie danych do tego momentu, ale nie mogę się zorientować, jak to osiągnąć. Ponadto chcę znaleźć najbliższy punkt w tym segmencie do punktu lokalizacji użytkownika. To jest to, co chcę wybrać i wrócić w moim zapytaniu.

Czy ktoś ma jakieś doświadczenie z funkcją geografii/geometrii, która może mi pomóc?

Dzięki!

+0

może chcesz dodać jakieś informacje typu pola. Na przykład, masz stały punkt opisujący lokalizację użytkownika, czy jest to para współrzędnych długości i szerokości geograficznej? Mam doświadczenie z funkcjami geograficznymi, ale potrzebuję więcej szczegółów ... – Sparky

+0

Zapewniam to z mojej aplikacji, więc przekazuję argument. Czuję się dobrze z prawie każdym typem danych. –

Odpowiedz

18

można przechowywać przedmioty w kolumnie GEOGRAPHY i stworzyć SPATIAL INDEX ponad ta kolumna.

Niestety SQL Server realizuje indeksów przestrzennych przez powierzchnię płytki i przechowywania identyfikatorów płytki prostym B-Tree indeksu, aby zwykły ORDER BY STDistance nie działa (dobrze, że działa, ale nie będzie korzystał z index).

Zamiast tego trzeba dokonać kwerendy podobny do tego:

DECLARE @mypoint GEOGRAPHY 
SET @mypoint = geography::STGeomFromText('POINT(@mylat, @mylon)', 4326); 

WITH num (distance) AS 
     (
     SELECT 1000 
     UNION ALL 
     SELECT distance + 1000 
     FROM num 
     WHERE distance <= 50000 
     ) 
SELECT TOP 1 m.* 
FROM num 
CROSS APPLY 
     (
     SELECT TOP 1 * 
     FROM mytable 
     WHERE myroad.STDistance(@mypoint) <= distance 
     ORDER BY 
       STDistance(@mypoint) 
     ) m 

ten sposób SQL Server najpierw szukać dróg w 1 kilometra od punktu, a następnie w ciągu 2 kilometrów, itd., Za każdym razem za pomocą indeksu.

Aktualizacja:

Jeśli masz kilka punktów w tabeli i chcemy znaleźć najbliższy punkt dla każdej z nich:

WITH num (distance) AS 
     (
     SELECT 1000 
     UNION ALL 
     SELECT distance + 1000 
     FROM num 
     WHERE distance <= 50000 
     ) 
SELECT mp.mypoint, m.* 
FROM @mypoints mp 
CROSS APPLY 
     (
     SELECT TOP 1 m.* 
     FROM num 
     CROSS APPLY 
       (
       SELECT TOP 1 * 
       FROM mytable 
       WHERE myroad.STDistance(@mypoint) <= distance 
       ORDER BY 
         STDistance(@mypoint) 
       ) m 
     ) m 
+2

Najlepsza odpowiedź Myślę, że kiedykolwiek spotkałem na StackOverflow. Dziękuję za poinformowanie mnie, że nie mogę po prostu "ZAMAWIĆ PRZEZ", co prawdopodobnie zakończyłoby wdrożenie. –

+0

@Pure: wystarczy zastosować moje zapytanie do '@ mypoints' – Quassnoi

+0

. Nie jestem pewien, czy @Pure Krome to zrozumiał, ale nie mogę tego zrozumieć. * Krzyż Zastosuj moje zapytanie do @ myPoints * ?? Nie rozumiem :(Czy możesz zaktualizować odpowiedź, proszę ??? – RPM1984