2010-01-09 4 views
10

J'essaie de créer une requête, mais j'ai quelques difficultés.SQL Server Géographie type de données le plus proche point sur la ligne

J'ai une base de données SQL Server 2008 avec une table qui inclut, entre autres champs, un champ géographique qui décrit les segments de route. (Ces données ont été importées à partir des données TIGER/Line du Recensement des États-Unis.)

J'ai un autre point fixe décrivant l'emplacement d'un utilisateur. Je veux trouver le segment de route le plus proche dans la base de données à ce stade, mais je n'arrive pas à comprendre comment y parvenir. En outre, je veux trouver le point le plus proche sur ce segment au point de localisation de l'utilisateur. C'est ce que je veux sélectionner et revenir dans ma requête.

Est-ce que quelqu'un a de l'expérience avec la fonctionnalité de géographie/géométrie qui peut m'aider?

Merci!

+0

Vous pouvez ajouter des informations de type de champ. Par exemple, vous avez un point fixe pour décrire l'emplacement de l'utilisateur, est-ce une paire de coordonnées Longitude et Latitude? J'ai de l'expérience avec les fonctions de géographie, mais j'ai besoin de plus de détails ... – Sparky

+0

Je fournis cela à partir de mon application, donc je passe un argument. Je vais bien à peu près tout type de données est nécessaire. –

Répondre

18

Vous pouvez stocker vos objets dans une colonne GEOGRAPHY et créer un SPATIAL INDEX sur cette colonne.

Malheureusement, SQL Server implémente des index spatiaux par carreler la surface et le stockage des identifiants de tuiles dans un index B-Tree plaine, si simple ORDER BY STDistance ne fonctionnera pas (bien, cela fonctionnera, mais ne sera pas utiliser l'index).

Au lieu de cela, vous devrez faire une requête similaire à ceci:

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 

De cette façon, SQL Server recherche d'abord les routes dans 1 km de votre point, puis dans les 2 kilomètres, etc., chaque fois en utilisant l'index.

Mise à jour:

Si vous avez des points multiples dans une table et que vous voulez trouver le point le plus proche pour chacun d'eux:

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

Meilleure réponse Je pense que je l'ai déjà rencontré sur StackOverflow. Merci de m'avoir fait savoir de ne pas simplement "ORDER BY", ce qui est probablement ce que j'aurais fini par implémenter. –

+0

@Pure: juste croiser appliquer ma requête à '@ mypoints' – Quassnoi

+0

salut. Je ne suis pas sûr si @Pure Krome l'a compris, mais je n'arrive pas à l'obtenir. * Cross Appliquer ma requête à @ myPoints * ?? Je ne comprends pas :(Pouvez-vous s'il vous plaît mettre à jour votre réponse, s'il vous plaît ??? – RPM1984

Questions connexes