MySQL 空间数据类型

MYSQL空间数据类型官方文档

1. 空间数据类型

1.1 Point

  • 特点:表示二维空间中的一个点。
  • 作用: 存储坐标点,通常用于表示地理位置或位置信息。
  • 场景: 适用于需要存储和查询特定地理坐标的场景,如地图应用。
CREATE TABLE locations (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    location POINT
);

1.2 LINESTRING

  • 特点: 表示由一组连接的线段构成的线。
  • 作用: 存储路径或线段,例如道路、河流等。
  • 场景: 适用于需要存储和查询路径或线段的场景,如导航系统。
CREATE TABLE routes (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    path LINESTRING
);

1.3 POLYGON

  • 特点: 表示由一组连接的线段构成的封闭多边形区域。
  • 作用: 存储区域或多边形,例如国家、城市的边界。
  • 场景: 适用于需要存储和查询多边形区域的场景,如地理信息系统。
CREATE TABLE regions (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    boundary POLYGON
);

1.4 GEOMETRY

  • 特点: 通用的几何类型,可以表示点、线、面等。
  • 作用: 用于存储任意几何形状。
  • 场景: 适用于需要灵活处理各种几何形状的场景。
CREATE TABLE shapes (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    geometry GEOMETRY
);

2. 索引

为了提高对空间数据类型的查询性能,可以使用空间索引。MySQL支持对空间数据类型创建空间索引,其中最常用的是R-tree索引。

2.1 创建和删除空间索引

对于InnoDBMyISAM 表,MySQL 可以使用与创建常规索引类似的语法创建空间索引,但使用关键字 SPATIAL。必须声明空间索引中的列NOT NULL。以下示例演示了如何创建空间索引:

  • CREATE TABLE

    CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326, SPATIAL INDEX(g));
  • ALTER TABLE

    CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326);
    ALTER TABLE geom ADD SPATIAL INDEX(g);
  • CREATE INDEX

    CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326);
    CREATE SPATIAL INDEX g ON geom (g);

SPATIAL INDEX创建 R 树索引。对于支持空间列的非空间索引的存储引擎,引擎会创建 B 树索引。空间值的 B 树索引对于精确值查找很有用,但对于范围扫描则不起作用。

优化器可以使用在 SRID 限制的列上定义的空间索引。有关更多信息,请参阅 第 11.4.1 节“空间数据类型”第 8.3.3 节“空间索引优化”

有关索引空间列的更多信息,请参阅 第 13.1.15 节 “CREATE INDEX 语句”

要删除空间索引,请使用ALTER TABLEDROP INDEX

示例:假设一个表geom包含超过 32,000 个几何图形,这些几何图形存储在 g类型为 的列中GEOMETRY。该表还有一AUTO_INCREMENTfid用于存储对象 ID 值。

mysql> DESCRIBE geom;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| fid   | int(11)  |      | PRI | NULL    | auto_increment |
| g     | geometry |      |     |         |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> SELECT COUNT(*) FROM geom;
+----------+
| count(*) |
+----------+
|    32376 |
+----------+
1 row in set (0.00 sec)

要在列上添加空间索引g,请使用以下语句:

mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
Query OK, 32376 rows affected (4.05 sec)
Records: 32376  Duplicates: 0  Warnings: 0

2.2 使用空间索引

优化器会调查可用的空间索引是否可以参与对在 子句中使用诸如MBRContains()or 之类的函数的查询的搜索。以下查询查找给定矩形中的所有对象: MBRWithin()WHERE

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom WHERE
    -> MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g)                                                  |
+-----+---------------------------------------------------------------+
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... |
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.00 sec)

用于EXPLAIN检查此查询的执行方式:

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM geom WHERE
    -> MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: geom
         type: range
possible_keys: g
          key: g
      key_len: 32
          ref: NULL
         rows: 50
        Extra: Using where
1 row in set (0.00 sec)

检查如果没有空间索引会发生什么:

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> EXPLAIN SELECT fid,ST_AsText(g) FROM g IGNORE INDEX (g) WHERE
    -> MBRContains(ST_GeomFromText(@poly),g)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: geom
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 32376
        Extra: Using where
1 row in set (0.00 sec)

执行SELECT不带空间索引的语句会产生相同的结果,但会导致执行时间从 0.00 秒增加到 0.46 秒:

mysql> SET @poly =
    -> 'Polygon((30000 15000,
                 31000 15000,
                 31000 16000,
                 30000 16000,
                 30000 15000))';
mysql> SELECT fid,ST_AsText(g) FROM geom IGNORE INDEX (g) WHERE
    -> MBRContains(ST_GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+
| fid | ST_AsText(g)                                                  |
+-----+---------------------------------------------------------------+
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... |
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... |
+-----+---------------------------------------------------------------+
20 rows in set (0.46 sec)

3. 空间函数

MYSQL官方文档

空间函数

姓名描述介绍
GeomCollection()从几何构造几何集合
GeometryCollection()从几何构造几何集合
LineString()从点值构造 LineString
MBRContains()一个几何体的MBR是否包含另一个几何体的MBR
MBRCoveredBy()一个MBR是否被另一个MBR覆盖
MBRCovers()一个MBR是否覆盖另一个MBR
MBRDisjoint()两种几何形状的 MBR 是否不相交
MBREquals()两个几何形状的MBR是否相等
MBRIntersects()两种几何形状的MBR是否相交
MBROverlaps()两种几何形状的MBR是否重叠
MBRTouches()两种几何形状的MBR是否接触
MBRWithin()一个几何体的 MBR 是否在另一个几何体的 MBR 内
MultiLineString()从 LineString 值构造 MultiLineString
MultiPoint()从 Point 值构造 MultiPoint
MultiPolygon()从多边形值构造多多边形
Point()从坐标构造点
Polygon()从 LineString 参数构造多边形
ST_Area()返回多边形或多多边形区域
ST_AsBinary(),ST_AsWKB()从内部几何格式转换为 WKB
ST_AsGeoJSON()从几何生成 GeoJSON 对象
ST_AsText(),ST_AsWKT()从内部几何格式转换为 WKT
ST_Buffer()返回距几何图形给定距离内的点的几何图形
ST_Buffer_Strategy()为 ST_Buffer() 生成策略选项
ST_Centroid()返回质心作为点
ST_Collect()将空间值聚合到集合中8.0.24
ST_Contains()一个几何体是否包含另一个几何体
ST_ConvexHull()返回几何体的凸包
ST_Crosses()一个几何体是否与另一个几何体交叉
ST_Difference()返回两个几何图形的点集差异
ST_Dimension()几何尺寸
ST_Disjoint()一个几何体是否与另一个几何体不相交
ST_Distance()一种几何体与另一种几何体的距离
ST_Distance_Sphere()地球上两个几何形状之间的最小距离
ST_EndPoint()线串的终点
ST_Envelope()返回几何图形的MBR
ST_Equals()一个几何体是否等于另一个几何体
ST_ExteriorRing()返回多边形的外环
ST_FrechetDistance()一种几何体与另一种几何体的离散 Fréchet 距离8.0.23
ST_GeoHash()生成 geohash 值
ST_GeomCollFromText(), ST_GeometryCollectionFromText(),ST_GeomCollFromTxt()从 WKT 返回几何集合
ST_GeomCollFromWKB(),ST_GeometryCollectionFromWKB()从 WKB 返回几何集合
ST_GeometryN()从几何集合中返回第 N 个几何
ST_GeometryType()返回几何类型的名称
ST_GeomFromGeoJSON()从 GeoJSON 对象生成几何图形
ST_GeomFromText(),ST_GeometryFromText()从 WKT 返回几何图形
ST_GeomFromWKB(),ST_GeometryFromWKB()从 WKB 返回几何图形
ST_HausdorffDistance()一种几何图形与另一种几何图形的离散豪斯多夫距离8.0.23
ST_InteriorRingN()返回 Polygon 的第 N 个内环
ST_Intersection()返回两个几何图形的点集交集
ST_Intersects()一个几何体是否与另一个几何体相交
ST_IsClosed()几何是否封闭且简单
ST_IsEmpty()几何体是否为空
ST_IsSimple()几何形状是否简单
ST_IsValid()几何图形是否有效
ST_LatFromGeoHash()从 geohash 值返回纬度
ST_Latitude()返回点的纬度8.0.12
ST_Length()返回 LineString 的长度
ST_LineFromText(),ST_LineStringFromText()从 WKT 构造 LineString
ST_LineFromWKB(),ST_LineStringFromWKB()从 WKB 构造 LineString
ST_LineInterpolatePoint()沿 LineString 指定百分比的点8.0.24
ST_LineInterpolatePoints()沿 LineString 指定百分比的点8.0.24
ST_LongFromGeoHash()从 geohash 值返回经度
ST_Longitude()返回点的经度8.0.12
ST_MakeEnvelope()围绕两点的矩形
ST_MLineFromText(),ST_MultiLineStringFromText()从 WKT 构造 MultiLineString
ST_MLineFromWKB(),ST_MultiLineStringFromWKB()从 WKB 构造 MultiLineString
ST_MPointFromText(),ST_MultiPointFromText()从 WKT 构造多点
ST_MPointFromWKB(),ST_MultiPointFromWKB()从 WKB 构造多点
ST_MPolyFromText(),ST_MultiPolygonFromText()从 WKT 构造多重多边形
ST_MPolyFromWKB(),ST_MultiPolygonFromWKB()从 WKB 构造多重多边形
ST_NumGeometries()返回几何集合中几何的数量
ST_NumInteriorRing(),ST_NumInteriorRings()返回 Polygon 中的内环数
ST_NumPoints()返回 LineString 中的点数
ST_Overlaps()一个几何体是否与另一个几何体重叠
ST_PointAtDistance()沿 LineString 给定距离的点8.0.24
ST_PointFromGeoHash()将 geohash 值转换为 POINT 值
ST_PointFromText()从 WKT 构造点
ST_PointFromWKB()从 WKB 构造点
ST_PointN()从 LineString 返回第 N 个点
ST_PolyFromText(),ST_PolygonFromText()从 WKT 构造多边形
ST_PolyFromWKB(),ST_PolygonFromWKB()从 WKB 构造多边形
ST_Simplify()返回简化的几何图形
ST_SRID()返回几何图形的空间参考系统 ID
ST_StartPoint()线串的起点
ST_SwapXY()返回 X/Y 坐标交换的参数
ST_SymDifference()返回两个几何图形的点集对称差
ST_Touches()一个几何体是否接触另一个几何体
ST_Transform()变换几何坐标8.0.13
ST_Union()返回两个几何图形的点集并集
ST_Validate()返回经过验证的几何图形
ST_Within()一个几何图形是否在另一个几何图形内部
ST_X()返回点的 X 坐标
ST_Y()返回Point的Y坐标

4. 实际项目和练习(Point)

4.1 MYSQL创建空间列

参考1.1

4.2 Java创建GeoPoint对象

/**
 * @author THF
 * @date 2023/11/22 10:58
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GeoPoint implements Serializable {
    /**
     * 经度
     */
    private BigDecimal longitude;

    /**
     * 纬度
     */
    private BigDecimal latitude;

}

4.3 在Java实体中使用

package com.pqkj.admin.service.modular.entity;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.pqkj.admin.service.core.easyExcel.RootDir;
import com.pqkj.admin.service.geo.GeoPoint;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import com.pqkj.admin.service.core.auth.vo.req.PageReqVO;

import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import com.fasterxml.jackson.annotation.JsonFormat;

import java.util.Date;
import java.util.List;

/**
 * 空间资产主表
 *
 * @author PQKJ
 * @since 2023-11-15
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("space_assets")
public class SpaceAssets extends PageReqVO implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @Schema(description = "主键", defaultValue = "主键")
    @TableId(value = "id")
    private String id;

    /**
     * 名称
     */
    @Schema(description = "名称", defaultValue = "名称")
    private String name;

    /**
     * 距离
     */
    @TableField(exist = false)
    private String distance;

    /**
     * 经纬度信息
     */
    private GeoPoint location;

    /**
     * 将单位(M)转换成 KM
     */
    public void covertDistance() {
        if (ObjectUtil.isNotEmpty(this.distance)) {
            //转换成BigDecimal类型
            BigDecimal distance = new BigDecimal(this.distance);
            if (distance.compareTo(new BigDecimal("1000")) > 0) {
                this.distance = distance.divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP) + "km";
            } else {
                this.distance = distance.setScale(2, RoundingMode.HALF_UP) + "m";
            }
        }
    }


    /**
     * 处理返回数据
     */
    public void returnDataHandle() {
        this.covertDistance();
    }

}

4.4 编写GeoPoint转换器

引入依赖

<dependency>
    <groupId>com.vividsolutions</groupId>
    <artifactId>jts</artifactId>
    <version>1.13</version>
</dependency>

编写转换器

package com.pqkj.admin.service.covert;

import com.pqkj.admin.service.geo.GeoPoint;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequenceFactory;
import com.vividsolutions.jts.io.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;

/**
 * @author THF
 * @date 2023/11/22 11:01
 */
public class GeoPointConverter {
    /**
     * Little endian or Big endian
     */
    private int byteOrder = ByteOrderValues.LITTLE_ENDIAN;
    /**
     * Precision model
     */
    private PrecisionModel precisionModel = new PrecisionModel();
    /**
     * Coordinate sequence factory
     */
    private CoordinateSequenceFactory coordinateSequenceFactory = CoordinateArraySequenceFactory.instance();
    /**
     * Output dimension
     */
    private int outputDimension = 2;

    /**
     * Convert byte array containing SRID + WKB Geometry into Geometry object
     */
    public GeoPoint from(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
            // Read SRID
            byte[] sridBytes = new byte[4];
            inputStream.read(sridBytes);
            int srid = ByteOrderValues.getInt(sridBytes, byteOrder);

            // Prepare Geometry factory
            GeometryFactory geometryFactory = new GeometryFactory(precisionModel, srid, coordinateSequenceFactory);

            // Read Geometry
            WKBReader wkbReader = new WKBReader(geometryFactory);
            Geometry geometry = wkbReader.read(new InputStreamInStream(inputStream));
            Point point = (Point) geometry;
            // convert to GeoPoint
            return new GeoPoint(BigDecimal.valueOf(point.getX()), BigDecimal.valueOf(point.getY()));
        } catch (IOException | ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Convert Geometry object into byte array containing SRID + WKB Geometry
     */
    public byte[] to(GeoPoint geoPoint) {
        if (geoPoint == null) {
            return null;
        }
        Coordinate coordinate = new Coordinate(geoPoint.getLongitude().doubleValue(), geoPoint.getLatitude().doubleValue());
        CoordinateArraySequence coordinateArraySequence = new CoordinateArraySequence(new Coordinate[]{coordinate}, 2);
        Point point = new Point(coordinateArraySequence, new GeometryFactory());
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            // Write SRID
            byte[] sridBytes = new byte[4];
            ByteOrderValues.putInt(point.getSRID(), sridBytes, byteOrder);
            outputStream.write(sridBytes);
            // Write Geometry
            WKBWriter wkbWriter = new WKBWriter(outputDimension, byteOrder);
            wkbWriter.write(point, new OutputStreamOutStream(outputStream));
            return outputStream.toByteArray();
        } catch (IOException ioe) {
            throw new IllegalArgumentException(ioe);
        }
    }
}

4.5 编写Mybatis类型处理器

package com.pqkj.admin.service.conf.mybatis.handler;

import com.pqkj.admin.service.covert.GeoPointConverter;
import com.pqkj.admin.service.geo.GeoPoint;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author THF
 * @date 2023/11/22 10:48
 */
@MappedTypes({GeoPoint.class})
public class PointTypeHandler extends BaseTypeHandler<GeoPoint> {

    GeoPointConverter converter = new GeoPointConverter();
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, GeoPoint parameter, JdbcType jdbcType) throws SQLException {
        ps.setBytes(i, converter.to(parameter));
    }

    @Override
    public GeoPoint getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return converter.from(rs.getBytes(columnName));
    }

    @Override
    public GeoPoint getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return converter.from(rs.getBytes(columnIndex));
    }

    @Override
    public GeoPoint getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return converter.from(cs.getBytes(columnIndex));
    }
}

4.6 Mybatis Plus扫描类型处理器

# Mybatis-Plus配置
mybatis-plus:
  type-handlers-package: com.pqkj.admin.service.conf.mybatis.handler

新增和修改时只要补充实体中的GeoPoint对象属性值,就可以正常插入和修改

4.7 查询某个点位附近几公里的数据

SQL示例:查询某点位附近5公里的数据

SELECT
    sa.id,
    sa.NAME,
    ST_DISTANCE_SPHERE (
        sa.location,
    ST_GEOMFROMTEXT ( 'POINT(113.556818 22.222774)' )) AS distance 
FROM
    space_assets AS sa
WHERE ST_DISTANCE_SPHERE (
        sa.location,
    ST_GEOMFROMTEXT ( 'POINT(113.556818 22.222774)' )) <= 5000 
ORDER BY
    distance desc

SQL中的5000为5千米,也就是5公里的意思,1000则为1公里。

在Java使用Mybatis查询时,需要将POINT(113.556818 22.222774)作为一个参数传进来

例如:

SELECT
    sa.id,
    sa.NAME,
    ST_DISTANCE_SPHERE (
        sa.location,
    ST_GEOMFROMTEXT ( #{lonLat} )) AS distance 
FROM
    space_assets AS sa
WHERE ST_DISTANCE_SPHERE (
        sa.location,
    ST_GEOMFROMTEXT ( #{lonLat} )) &lt;= #{distance} 
ORDER BY
    distance desc
最后修改:2024 年 04 月 26 日
如果觉得我的文章对你有用,请随意赞赏