【问题标题】:how to get distance in meter如何获得以米为单位的距离
【发布时间】:2017-02-01 07:09:01
【问题描述】:

我有下面的存储程序我想检查我的汽车纬度经度的距离,如果距离以米为单位小于 500,则最近的地理围栏显示地理围栏 id 哪个地理围栏 id 最近的汽车纬度经度。如果汽车纬度经度最近的多边形显示多边形 ID,如果矩形显示矩形 id 我是 sql server 的新手,所以我在这里请专业人士帮助我,我非常感谢你,演示表在共享链接中,

question and demo table is here

CREATE TABLE CarDistance 
(
ID int IDENTITY(1,1) PRIMARY KEY,
car_id int,
latitude float,
longitude float

)
insert into CarDistance values(1234, '52.582191','-2.878418')

CREATE TABLE tblgeofencing2  
(
ID int IDENTITY(1,1) PRIMARY KEY,
car_id int,
ShapeType  varchar(255),
PolygonLatLng  varchar(max),
minlatitude [float] NULL,
    [minlongitude] [float] NULL,
    [maxlatitude] [float] NULL,
    [maxlongitude] [float] NULL,
)

insert into tblgeofencing2 values(123, 'polygon','24.835300590037598 67.06858277320862,24.835933468801272 67.06929624080658,24.83532979989791 67.07035303115845,24.83454113125045 67.0697683095932,24.835300590037598 67.06858277320862',NULL,NULL,NULL,NULL)
insert into tblgeofencing2 values(1234, 'rectangle','NULL','52.582191','-2.878418','52.233687','-2.702637')

Alter PROCEDURE [dbo].[Sp_CheckCarStatusMeter]  
 DECLARE @g GEOGRAPHY, 
         @ID INT,
     @curVal     INT, 
         @preVal     INT ,  
     @CarSuggested INT,  
     @carlatprevious VARCHAR(10), 
         @carlongprevious VARCHAR(10), 
    @AllLatitudeLongitude VARCHAR(255),     
         @pprevious GEOGRAPHY

 DECLARE SuggestCursor CURSOR  FOR
       SELECT TOP 100 rtha.car_id , rtha.latitude,  
           rtha.longitude 
     FROM   CarDistance rtha WHERE rtha.car_id = 123;
     OPEN SuggestCursor;  
     FETCH NEXT FROM SuggestCursor INTO @CarSuggestedID , @carlatprevious , @carlongprevious; 

     WHILE (@@FETCH_STATUS = 0)    
 BEGIN       

     DECLARE ShapeCursor CURSOR FOR  
  SELECT g.ID, @CarSuggestedID,  g.ShapeType  FROM   tblgeofencing AS g
         WHERE  car_id =@CarSuggestedID 
  FETCH NEXT FROM ShapeCursor INTO @ID , @CarIdx , @ShapeType; 

     WHILE (@@FETCH_STATUS = 0)
     BEGIN 
     IF (@ShapeType = 'polygon')
         BEGIN --Polygon IF 
             PRINT 'polygon if'; 
             SELECT @GeofenceIDnew = g.GeoFenceId,  @minY = g.PolygonLatLng ROM   tblgeofencing AS g
             WHERE  g.ID = =@CarSuggestedID 
             SET @g = geography ::STPolyFromText('POLYGON((' + @AllLatitudeLongitude + '))', 4326);           
             SET @pprevious = geography ::STPointFromText(
                     'POINT(' + @carlatprevious + ' ' + @carlongprevious +  ')',  4326   ); 
             SELECT @preVal = @g.STIntersects(@pprevious) 
             PRINT @preVal  
             IF @curVal = 1 AND @preVal = 0 
             BEGIN  
                PRINT 'Enter In GEOFENCE';  
                 SELECT @geofencename = geofenceName, 
                        @geofenceidforresult = ID  
                 FROM   tblgeofencing where ID = @CarSuggestedID;
                 INSERT INTO tblGeofenceCarStatus  
                 VALUES 
                   ( 
                     @CarSuggestedID,  @geofenceidforresult,@geofencename,  
                     @gpstime, @g.STDistance(@pprevious), 'Enter' ); 

             END  
        ELSE
BEGIN
Print Not in Geofence
END

         END; --- END POLYGON IF 
   FETCH NEXT FROM ShapeCursor INTO @ID , @CarIdx , @ShapeType;  



     END; --- END CHECK GEOFENCING RECTANGLE OR CIRCLE OR PLYGON 


      FETCH NEXT FROM SuggestCursor INTO @CarSuggestedID , @carlatprevious , @carlongprevious;  



       END;
     CLOSE ShapeCursor;  
      DEALLOCATE ShapeCursor;  
        CLOSE SuggestCursor;
       DEALLOCATE SuggestCursor; 
     SELECT * FROM   tblGeofenceCarStatus;    

 END;  

END; --- END SP BEGIN  STATEMENT

【问题讨论】:

    标签: sql-server sql-server-2012 sql-server-2008-r2 geography


    【解决方案1】:

    以下解决方案将:

    • 确定每辆车的最近位置
    • 识别每辆车的先前位置
    • 根据多边形字符串或矩形坐标构建地理围栏多边形
    • 识别当前位于地理围栏 500 米范围内(从外部)或位于地理围栏内的汽车
    • 显示与之前位置的地理围栏的距离
    ;
    WITH car_location_seq AS (
            SELECT   car_id
                    ,ID
                    ,latitude
                    ,longitude
                    ,ROW_NUMBER() OVER (PARTITION BY car_id ORDER BY ID DESC) AS Pos_Sequence
            FROM #CarDistance
    ),
    car_location AS (
            SELECT   c1.car_id
                    ,geography::Point(c1.longitude, c1.latitude,  4326) AS Geo_Point_Current
                    ,CASE WHEN c2.car_id IS NOT NULL THEN geography::Point(c2.longitude, c2.latitude,  4326) END AS Geo_Point_Previous
            FROM car_location_seq c1 -- Most recent position
                LEFT JOIN car_location_seq c2 -- Previous position
                    ON c1.car_id = c2.car_id
                    AND c2.Pos_Sequence = 2
            WHERE c1.Pos_Sequence = 1
    ),
    fences AS (
            SELECT   ID
                    ,Car_ID
                    ,CASE   WHEN ShapeType = 'polygon' THEN geography::STPolyFromText('POLYGON((' + PolygonLatLng + '))', 4326)
                            WHEN ShapeType = 'rectangle' THEN geography::STPolyFromText('POLYGON((' + 
                                    CAST(maxlatitude AS VARCHAR(100)) + ' ' + CAST(minlongitude AS VARCHAR(100)) + ', ' + 
                                    CAST(minlatitude AS VARCHAR(100)) + ' ' + CAST(minlongitude AS VARCHAR(100)) + ', ' + 
                                    CAST(minlatitude AS VARCHAR(100)) + ' ' + CAST(maxlongitude AS VARCHAR(100)) + ', ' + 
                                    CAST(maxlatitude AS VARCHAR(100)) + ' ' + CAST(maxlongitude AS VARCHAR(100)) + ', ' + 
                                    CAST(maxlatitude AS VARCHAR(100)) + ' ' + CAST(minlongitude AS VARCHAR(100)) + 
                                    '))', 4326)
                    END AS Geo_Polygon
            FROM #tblgeofencing2
    )
    
    SELECT   f.ID AS Fence_ID
            ,c.car_id
            ,c.Geo_Point_Current
            --,c.Geo_Point_Current.STAsText()
            ,f.Geo_Polygon
            --,f.Geo_Polygon.STAsText()
            ,f.Geo_Polygon.STIntersects(c.Geo_Point_Current) AS Is_Inside_Fence_Current
            ,f.Geo_Polygon.STIntersects(c.Geo_Point_Previous) AS Is_Inside_Fence_Previous
            ,f.Geo_Polygon.STDistance(c.Geo_Point_Current) AS Distance_Current
            ,f.Geo_Polygon.STDistance(c.Geo_Point_Previous) AS Distance_Previous
    --INTO #Relevant_Car_Positions
    FROM fences f
        INNER JOIN car_location c
            ON f.car_id = c.car_id
    
    WHERE f.Geo_Polygon.STDistance(c.Geo_Point_Current) < 500
    ;
    

    样本输出:

    您应该能够调整此代码以满足您的需要。例如,您可以首先通过取消注释INTO #Relevant_Car_Positions 将查询输出存储到临时表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 2018-04-02
      • 2011-12-21
      • 1970-01-01
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      相关资源
      最近更新 更多