首页 新闻 赞助 找找看

本人新手,SQL自写过程,求简化及优化, 根据平面空间geometry数据类型查询区域内经纬

0
悬赏园豆:80 [已解决问题] 解决于 2015-06-03 13:11

环境: sql2008, 数据5万左右(场所地址带经纬度)

需求: 在地图上画出多边形,取得多边形数据(各点经纬度), 从数据库中查询出该多边形区域内的所有场所。 

场所表设计:

IF OBJECT_ID ( 'dbo.SpatialTable', 'U' ) IS NOT NULL DROP TABLE dbo.SpatialTable;
GO
CREATE TABLE SpatialTable ( id int IDENTITY (1,1), Lng VARCHAR(12),Lat VARCHAR(12) ,  geom geometry,     adress varchar );
GO

数据示例:

INSERT INTO SpatialTable (Lng,lat)VALUES ('116.307672','40.055678'); 
INSERT INTO SpatialTable (Lng,lat)VALUES ('116.307672','40.054546'); 

存储过程:

/****** Object:  StoredProcedure [dbo].[aa]    Script Date: 05/26/2015 09:55:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


  ---------------------------------
--用途:根据多边线数据查询区域内的场所
--说明:
-- 2015-05-26
------------------------------------

create  PROCEDURE [dbo].SP_QueryLatLng @geometry VARCHAR(500) --传入值(多边形geometry类型), 如:POLYGON ((116.304834 40.05543, 116.305373 40.051923, 116.312631 40.054712, 116.309577 40.057749, 116.304834 40.05543))
AS
    DECLARE @g GEOMETRY
    SET @g = geometry::STGeomFromText(@geometry, 0) --转换

    DECLARE @n INT
    DECLARE @rowcount INT
    DECLARE @id INT
    DECLARE @h GEOMETRY
    DECLARE @lng VARCHAR(12) --经度 
    DECLARE @lat VARCHAR(12) --纬度


    IF OBJECT_ID('Tempdb..#temp') IS NOT NULL
        DROP TABLE  #temp
        
    IF OBJECT_ID('Tempdb..#Resultset') IS NOT NULL
        DROP TABLE  #temp

    CREATE TABLE #temp --根据这个临时表进行遍历
        (
          id INT IDENTITY(1, 1) ,
          lng VARCHAR(12) ,
          lat VARCHAR(12) ,
          adress VARCHAR(200)
        )

    CREATE TABLE #Resultset  --输出的临时表结果集
        (
          id INT ,
          lng VARCHAR(12) ,
          lat VARCHAR(12) ,
          adress VARCHAR(200)
        )


    INSERT  INTO #temp
            SELECT  Lng ,
                    Lat ,
                    adress
            FROM    SpatialTable  --将符合条件的场所信息插入临时表准备遍历
            
    SET @rowcount = @@rowcount
    SET @n = 1
    WHILE @n < @rowcount
        BEGIN
            SELECT  @lng = lng ,
                    @lat = lat
            FROM    #temp
            WHERE   id = @n; 
            SET @h = geometry::STGeomFromText('POINT(' + @lng + ' ' + @lat
                                              + ')', 0);
            IF @g.STContains(@h) = 1
                BEGIN
                    INSERT  INTO #Resultset
                            ( id, lng, lat, adress )
                            SELECT  *
                            FROM    #temp
                            WHERE   id = @n
                END   
            SET @n = @n + 1
        END
    SELECT  *     FROM    #Resultset

 

调用存储过程示例:

EXEC dbo.SP_QueryLatLng @geometry = 'POLYGON ((116.304834 40.05543, 116.305373 40.051923, 116.312631 40.054712, 116.309577 40.057749, 116.304834 40.05543))' 

 

我刚学数据库不久,写的存储过程,用了两个临时表(没有用游标),数据现在是5万左右,还在不断增加,  项目经理说可以用嵌套查询, 循环都不需要用, 我没写出来(报语法错误)。有没有做过数据库几何图形数据查询的大神, 帮忙看下.

我表结构示例数据都给了, 能直接在sql中运行, 希望大神帮忙看看, 哪些不足。 

问题补充:

需求就是, 在地图上画一个矩形或者其它多边线, 取得各个点的坐标, 然后去数据库中查询这个形状类的所有场所。 

奋奋奋的主页 奋奋奋 | 初学一级 | 园豆:32
提问于:2015-05-26 10:54
< >
分享
最佳答案
0

这个难应该是难在怎么判断点在多边形内。如果是矩形到是很容易啊

select * from tb where x between x1 and x2 and y between y1 and y2. 

这个主要是算法。你先得把点在多边形内的算法整出来的。我感觉还是不好整。多边形还分凸多边形,凹多边形,特别是凹多边形这个难判断。

收获园豆:79
gw2010 | 小虾三级 |园豆:1487 | 2015-05-26 14:57

sql 08以上已经支持空间查询了, 这个算法不劳费心, 主要是我写的那个过程, 能否简化

奋奋奋 | 园豆:32 (初学一级) | 2015-05-26 16:01

@奋奋奋: 按你有算法支持那就很简单了。一句查询就可以了啊。

select * from spatialtable where @g.STContains(geometry::STGeomFromText('POINT('+lng+' '+lat+')',0))=1

gw2010 | 园豆:1487 (小虾三级) | 2015-05-26 16:09

@gw2010: 

3Q, 

select * from spatialtable where geometry::STGeomFromText('POLYGON ((116.304834 40.05543, 116.305373 40.051923, 116.312631 40.054712, 116.309577 40.057749, 116.304834 40.05543))', 0).STContains(geometry::STGeomFromText('POINT('+lng+' '+lat+')',0))=1

.STContains(这个位置不知道能否嵌套查询不)。  如果是这样就可以省去自己写遍历了。 

奋奋奋 | 园豆:32 (初学一级) | 2015-05-26 16:24
其他回答(1)
0

mark

收获园豆:1
请叫我头头哥 | 园豆:9382 (大侠五级) | 2015-05-27 19:25
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册