纬度和经度的数据类型是什么?

use*_*404 124 postgresql types postgis latitude-longitude

我是PostgreSQL和PostGIS的新手.我想在PostgreSQL 9.1.1数据库表中存储纬度和经度值.我将计算两点之间的距离,通过使用此位置值找到更近的点.

我应该将哪种数据类型用于纬度和经度?

Erw*_*ter 123

您可以使用数据类型point- 组合(x,y)可以是您的纬度/经度.占用16个字节:float8内部有2个数字.

或者使它成为两列类型float(= float8double precision).每个8个字节.
real(= float4)如果不需要额外的精度.每个4个字节.
或者即使numeric你需要绝对的精确度.每组4个数字2个字节,加上3-8个字节的开销.

阅读有关数字类型几何类型的精细手册.


geometrygeography数据类型由附加模块提供了PostGIS并占据一个在你的表列.每个占用一个点的32个字节.还有一些像SRID那样的额外开销.这些类型存储(长/纬),而不是(纬度/长度).

在这里开始阅读PostGIS手册.

  • 它真的是一本精美的手册不是吗?文档中的一个光辉榜样. (7认同)
  • 我不建议使用`float`数据类型.它使得坐标计算非常复杂.您应该使用PostGIS和`geography`数据类型进行此类计算. (4认同)
  • @丹:取决于。请提出一个新的*问题*并提供详细信息。您始终可以链接到此链接以获取上下文。评论不是提出新问题的地方。 (2认同)

Dar*_*ski 29

在PostGIS中,对于具有纬度和经度的点,存在地理数据类型.

要添加列:

alter table your_table add column geog geography;
Run Code Online (Sandbox Code Playgroud)

要插入数据:

insert into your_table (geog) values ('SRID=4326;POINT(longitude latitude)');
Run Code Online (Sandbox Code Playgroud)

4326是空间参考ID,它表示经度和纬度的数据,与GPS相同.更多关于它:http://epsg.io/4326

顺序是经度,纬度 - 所以如果你把它绘制成地图,它是(x,y).

要找到最近的点,首先需要创建空间索引:

create index on your_table using gist (geog);
Run Code Online (Sandbox Code Playgroud)

然后请求,例如,5最接近给定点:

select * 
from your_table 
order by geog <-> 'SRID=4326;POINT(lon lat)' 
limit 5;
Run Code Online (Sandbox Code Playgroud)

  • 澄清 SRID 4326 希望按该顺序提供纬度经度。但 PostGIS 对 SRID 4326 的解释需要按该顺序排列经度纬度。示例对于 PostGIS 使用是正确的。https://postgis.net/2013/08/18/tip_lon_lat/ (2认同)

tvi*_*ira 22

我强烈支持PostGis.它特定于这种数据类型,它具有开箱即用的方法来计算点之间的距离,以及您将来可以发现有用的其他GIS操作


Han*_*ter 7

如果您不需要 PostGIS 提供的所有功能,Postgres(现在)提供了一个名为earthdistance的扩展模块。它根据距离计算的精度需求使用立方体数据类型。

您现在可以使用earth_box函数来(例如)查询某个位置特定距离内的点。


Tim*_*ude 6

在 PostGIS 中,几何优于地理(圆形地球模型),因为计算更简单,因此速度更快。它还具有更多可用功能,但在很长的距离内精度较低。

将您的 CSV 长和经纬度字段导入到DECIMAL(10,6)列中。6 位数是 10 厘米的精度,对于大多数用例来说应该足够了。然后将导入的数据转换为正确的 SRID

错误的方法!

/* try what seems the obvious solution */
DROP TABLE IF EXISTS public.test_geom_bad;
-- Big Ben, London
SELECT ST_SetSRID(ST_MakePoint(-0.116773, 51.510357),4326) AS geom
INTO public.test_geom_bad;

Run Code Online (Sandbox Code Playgroud)

正确的方法

/* add the necessary CAST to make it work */
DROP TABLE IF EXISTS public.test_geom_correct;
SELECT ST_SetSRID(ST_MakePoint(-0.116773, 51.510357),4326)::geometry(Geometry, 4326) AS geom
INTO public.test_geom_correct;
Run Code Online (Sandbox Code Playgroud)

验证 SRID 不为零!

/* now observe the incorrect SRID 0 */
SELECT * FROM public.geometry_columns
WHERE f_table_name IN ('test_geom_bad','test_geom_correct');
Run Code Online (Sandbox Code Playgroud)

使用 WKT 查看器验证 long lat 参数的顺序,然后

SELECT ST_AsEWKT(geom) FROM public.test_geom_correct

然后索引它以获得最佳性能

CREATE INDEX idx_target_table_geom_gist
    ON target_table USING gist(geom);
Run Code Online (Sandbox Code Playgroud)