时空聚合函数可以将乱序存储的点按序排列并进行聚合计算,多用于车联网、GIS、物联网等有大量时空数据产生,且有轨迹分析需求的场景。
引擎与版本
要求Lindorm SQL为2.6.8及以上版本。如何查看Lindorm SQL的版本,请参见SQL版本说明。
函数列表
Lindorm Ganos支持的聚合函数如下表所示。
函数 | 说明 |
将乱序存储的点按时间进行排序并拼接为轨迹,计算并返回该轨迹的球面长度,单位为米(m)。 | |
基于给定的降采样时间和空间阈值,将乱序存储的点按时间从早到晚排序并按阈值降采样,生成轨迹。 | |
将乱序存储的点按时间排序并拼接为轨迹,基于时间阈值将该轨迹分割为轨迹段,计算并返回每条轨迹段的起止点的坐标和时间。 |
ST_Length_Rows
将乱序存储的点按时间进行排序并拼接为轨迹,计算并返回该轨迹的球面长度,单位为米(m)。
ST_Length_Rows
函数可以与GROUP BY
语句联用,用于返回指定列中的点聚合而成的轨迹的球面长度。
您需要通过主键来保证点的顺序,否则计算出的长度可能与预期不符。例如,在车联网场景中,可以使用车辆ID和时间戳timestamp作为主键来保证点的顺序。
语法
double ST_Length_Rows(point column)
参数说明
参数 | 描述 |
point column | 指定的Geometry对象。类型为POINT。 |
示例
本示例的查询基于如下建表语句和示例数据:
CREATE TABLE test_len (carid VARCHAR, collect_time TIMESTAMP, p GEOMETRY(POINT), PRIMARY KEY(carid, collect_time));
INSERT INTO test_len (carid, collect_time,p) VALUES('car1', '2023-09-12 00:04:02', ST_GeomFromText('POINT (111.40269 35.61695)')),
('car1', '2023-09-12 00:09:07', ST_GeomFromText('POINT (111.40127 35.616096)')),
('car1', '2023-09-12 00:14:03', ST_GeomFromText('POINT (111.400604 35.616013)')),
('car1', '2023-09-12 00:20:13', ST_GeomFromText('POINT (111.399734 35.613983)')),
('car1', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)')),
('car2', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)'));
示例1:计算p列中,所有carid为car1的点形成的轨迹的球面长度。
SELECT ST_LENGTH_ROWS(p) FROM test_len WHERE carid='car1';
返回结果如下:
+--------------------+ | st_length_rows(p) | +--------------------+ | 805.55323541493414 | +--------------------+
示例2:计算按carid分组聚合后,每条轨迹的球面长度。
SELECT carid,ST_LENGTH_ROWS(p) as len FROM test_len WHERE carid<='car2' GROUP BY carid;
返回结果如下:
+-------+--------------------+ | carid | len | +-------+--------------------+ | car1 | 805.55323541493414 | | car2 | 0 | +-------+--------------------+
ST_Resample
基于给定的降采样时间和空间阈值,将乱序存储的点按时间从早到晚排序并按阈值降采样,生成轨迹。
在使用ST_Resample
函数时需提供单个轨迹对象和轨迹点范围的过滤条件。不支持与GROUP BY
语句联用。
语法
String ST_Resample(String geomColumnName, String timeColumnName, String config)
String ST_Resample(String xColumnName, String yColumnName, String timeColumnName, String config)
参数说明
参数 | 描述 |
geomColumnName | 指定的Geometry对象。类型为POINT。 |
xColumnName | 经度列。类型为DOUBLE,必须与yColumnName参数一起使用。 |
yColumnName | 纬度列。类型为DOUBLE,必须与xColumnName参数一起使用。 |
timeColumnName | 时间列名,轨迹点按该时间列增序构造。支持TIME/TIMESTAMP/LONG类型,LONG类型单位必须为毫秒(ms)。 |
config | 以JSON格式给定的降采样参数,类型为STRING。格式为:{"参数名": 取值}。 |
config包含以下可选参数:
参数 | 描述 |
downsample_time | 降采样时间阈值。降采样后相邻轨迹点之间的时间间隔均大于此参数值。 单位为毫秒(ms),默认值为-1,支持INT和LONG类型。 |
downsample_distance | 降采样距离阈值,即依据指定的简化算法(vm、dp或topologypreserving)对轨迹的几何形状进行简化时给定的计算阈值。 单位与点坐标单位相同,默认值为-1.0,支持INT、LONG、FLOAT和DOUBLE类型。 |
simplifer | 进行降采样时的简化算法,类型为STRING,支持以下选项:
|
返回值
返回降采样后按时间排序的轨迹点序列。返回值类型为STRING,格式为:[{\"x\":经度,\"y\":纬度,\"t\":时间}, {\"x\":经度,\"y\":纬度,\"t\":时间}, ...]
。
示例
本示例的查询基于如下建表语句和示例数据:
CREATE TABLE gps_points (account_id VARCHAR, collect_time TIMESTAMP, gps_point GEOMETRY(POINT), PRIMARY KEY(account_id, collect_time));
INSERT INTO gps_points(account_id, collect_time, gps_point) VALUES ('001', '2023-11-10 11:00:30', ST_MakePoint(113.665431, 34.773)),
('001', '2023-11-10 11:00:31', ST_MakePoint(113.665432, 34.773)),
('001', '2023-11-10 11:00:32', ST_MakePoint(113.665433, 34.773)),
('001', '2023-11-10 11:00:33', ST_MakePoint(113.665434, 34.774));
查询表gps_points
中,指定车辆在指定时间范围内的行驶轨迹,返回使用Visvalingam-Whyatt算法按照0.0001的距离阈值降采样后的轨迹。
SELECT ST_Resample(gps_point, collect_time,'{"downsample_distance": 0.0001, "simplifier": "vw"}') as resampled_traj FROM gps_points WHERE collect_time >= '2023-11-10 00:00:00' and collect_time <= '2023-11-11 00:00:00' and account_id='001';
返回结果如下:
+----------------------------------------------------------------------------------------------------------------------+
| resampled_traj |
+----------------------------------------------------------------------------------------------------------------------+
| [{"x":113.665431,"y":34.773,"t":"2023-11-10 11:00:30.0"},{"x":113.665434,"y":34.774,"t":"2023-11-10 11:00:33.0"}] |
+----------------------------------------------------------------------------------------------------------------------+
ST_TrajectoryProfile
将乱序存储的点按时间排序并拼接为轨迹,基于时间阈值将该轨迹分割为轨迹段,计算并返回每条轨迹段的起止点的坐标和时间。
ST_TrajectoryProfile
函数需要与GROUP BY
语句联用,用于计算聚合分组后,每个组中各个轨迹段的起止点的坐标和时间。
ST_TrajectoryProfile
函数通常也会与ST_DWithinSphere等空间关系函数联用。用于计算轨迹段进入指定区域时第一个点的坐标和时间,以及该轨迹段离开指定区域前最后一个点的坐标和时间。
语法
String ST_TrajectoryProfile(String geomColumnName, String timeColumnName,long thresh)
String ST_TrajectoryProfile(String xColumnName, String yColumnName, String timeColumnName,long thresh)
参数
参数 | 描述 |
geomColumnName | 指定的Geometry对象。类型为POINT。 说明 如果您在存储点数据时,使用的数据类型是Point类型,查询时请选择该参数。 |
xColumnName | 经度列。类型为DOUBLE,必须与yColumnName参数一起使用。 说明 如果您使用区分经纬度的方式存储点数据,查询时请选择该参数。 |
yColumnName | 纬度列。类型为DOUBLE,必须与xColumnName参数一起使用。 说明 如果您使用区分经纬度的方式存储点数据,查询时请选择该参数。 |
timeColumnName | 时间列,轨迹点按该时间列增序构造。 |
thresh | 可选参数。时间阈值,单位为毫秒(ms)。按时间排序后,相邻两轨迹点的时间间隔小于该阈值则属于同一轨迹段,大于该阈值则分属不同轨迹段。默认值为10000 ms。 |
返回值
返回JSON STRING,格式为:
{"轨迹段编号":"{\"endY\":终点纬度,\"endX\":终点经度,\"startY\":起点纬度,\"startTime\":起点时间,\"startX\":起点经度,\"endTime\":终点时间}"}
。
示例
本示例的查询基于如下建表语句和示例数据:
CREATE TABLE test_traj (carid VARCHAR, collect_time TIMESTAMP, p GEOMETRY(POINT), status VARCHAR, PRIMARY KEY(z-order(p), carid, collect_time));
INSERT INTO test_traj (carid, collect_time, p, status) VALUES('car1', '2023-09-12 00:04:02', ST_GeomFromText('POINT (111.40269 35.61695)'), 'normal'),
('car1', '2023-09-12 00:09:07', ST_GeomFromText('POINT (111.40127 35.616096)'), 'normal'),
('car1', '2023-09-12 00:14:03', ST_GeomFromText('POINT (111.400604 35.616013)'), 'normal'),
('car1', '2023-09-12 00:20:13', ST_GeomFromText('POINT (111.399734 35.613983)'), 'normal'),
('car1', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)'), 'normal'),
('car2', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)'), 'normal');
查询test_traj
表中,指定时间范围和空间范围内,每个设备采集到的轨迹段的出入点坐标和出入时间。
SELECT carid, st_trajectoryprofile(p, collect_time, 30000) as trajprofile FROM test_traj WHERE st_dwithinsphere(st_geomfromtext('POINT (111.40217 35.616386)'), p, 100.0) and collect_time >= '2023-09-12 00:09:07' and collect_time <= '2023-09-20 00:09:07' group by carid;
使用时,如果查询利用了二级索引,该索引需要添加所有查询涉及到的列(包括聚合键、过滤条件列和函数参数列)为冗余列,避免回查主表。例如,在上述示例中,二级索引需要同时冗余carid
、p
和collect_time
列。
返回结果如下:
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| carid | trajprofile |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| car1 | {"0":"{\"endY\":35.616096,\"endX\":111.40127,\"startY\":35.616096,\"startTime\":1694448547000,\"startX\":111.40127,\"endTime\":1694448547000}","1":"{\"endY\":35.616386,\"endX\":111.40217,\"startY\":35.616386,\"startTime\":1694449641000,\"startX\":111.40217,\"endTime\":1694449641000}"} |
| car2 | {"0":"{\"endY\":35.616386,\"endX\":111.40217,\"startY\":35.616386,\"startTime\":1694449641000,\"startX\":111.40217,\"endTime\":1694449641000}"} |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+