[英]How to aggregate multiple points by two columns and create a LineString / MultiLineString out of them
I have a table called locations that has these rows: 我有一个名为locations的表,其中包含以下行:
id uuid NOT NULL,
"deviceId" text COLLATE pg_catalog."default",
"userId" uuid,
"userName" text COLLATE pg_catalog."default",
"creationDateTime" timestamp with time zone,
shape geometry,
CONSTRAINT id PRIMARY KEY (id)
Imagine My user register points per hours into this table at shape
column .When register the time of that point that is registered into table, saved into creationDateTime
column like this 2018-08-22 00:03:41.649+04:30
. 想象一下,我的用户每小时将点数注册到该表的
shape
列中。当注册该点的时间并注册到表中时,将其保存到creationDateTime
列中,如下所示: 2018-08-22 00:03:41.649+04:30
。
How can i extract this info : 我如何提取此信息:
each User ---- each day ---- list of geometry(shape column)
in example: each User ---- each day ---- list of geometry(shape column)
例如each User ---- each day ---- list of geometry(shape column)
:
User1 in first day has list of geometry points.
第一天的User1包含几何点列表。 User1 in seccond day has list of geometry points and so on...
第二天的User1包含几何点列表等等。
I made this query by mongo for same project: 我通过mongo对同一项目进行了此查询:
{$project: {
_id: 0,
uId : "$UserId",
dId : "$DeviceId",
ts :"$CreationDateTime",
point : "$Point"
}
},
{$group: {
_id :{
did: "$dId",
day: { $dayOfMonth: "$ts" }
},
docs: { $push: "$$ROOT" }
}
},
{
$sort:{"_id.day": -1}
}
But how could i do that with postgresql? 但是我怎么用postgresql做到这一点? There is not exist this kind of aggregation on postgre and i am new on postgresql.
在postgre上不存在这种聚合,而在postgresql上我是新来的。 This is my query :
这是我的查询:
(Select test1."deviceId",test1."shape", test1."creationDateTime" From
(Select * from locations) as test1 Group By test1."deviceId",test1."shape",test1."creationDateTime"
ORDER BY test1."creationDateTime")
This query did not suitable result and i know this query has a problem. 此查询不适合结果,我知道此查询有问题。 deviceId of users frequently repeated with other row.How can i handle it?
用户的deviceId经常与其他行重复出现。我该如何处理?
At the end i want to create multi-poly-line per user - per day - multi poly line
最后,我想为
per user - per day - multi poly line
创建多折线per user - per day - multi poly line
There are probably a million ways to answer this question. 可能有上百万种方法可以回答这个问题。 Here is one of them:
这是其中之一:
Considering your table structure .. 考虑你的表结构..
CREATE TEMPORARY TABLE locations
(id uuid,
deviceId text COLLATE pg_catalog."default",
userId uuid,
userName text COLLATE pg_catalog."default",
creationDateTime timestamp with time zone,
shape geometry);
.. And these sample data .. ..以及这些样本数据..
INSERT INTO locations (userId, creationDateTime, shape)
VALUES ('d1166a84-ab66-11e8-98d0-529269fb1459',CURRENT_DATE,'POINT(-1.25 51.75)'),
('d1166a84-ab66-11e8-98d0-529269fb1459',CURRENT_DATE,'POINT(-1.15 52.96)'),
('d1166a84-ab66-11e8-98d0-529269fb1459',CURRENT_DATE,'POINT(-0.13 50.82)'),
('d1166a84-ab66-11e8-98d0-529269fb1459',CURRENT_DATE-1,'POINT(-2.22 53.48)'),
('d1166a84-ab66-11e8-98d0-529269fb1459',CURRENT_DATE-1,'POINT(-0.11 51.51)');
.. you can aggregate the points per user + date and create a LINESTRING
using ST_MakeLine
with a GROUP BY
: ..您可以汇总每个用户+日期的积分,并使用
ST_MakeLine
和GROUP BY
创建LINESTRING
:
SELECT userId, creationDateTime, ST_AsText(ST_MakeLine(shape))
FROM locations
GROUP BY userId, creationDateTime
ORDER BY creationDateTime;
userid | creationdatetime | st_astext
--------------------------------------+------------------------+-------------------------------------------------
d1166a84-ab66-11e8-98d0-529269fb1459 | 2018-08-28 00:00:00+02 | LINESTRING(-2.22 53.48,-0.11 51.51)
d1166a84-ab66-11e8-98d0-529269fb1459 | 2018-08-29 00:00:00+02 | LINESTRING(-1.25 51.75,-1.15 52.96,-0.13 50.82)
(2 Zeilen)
Graphical depiction of user d1166a84-ab66-11e8-98d0-529269fb1459
at 2018-08-28 00:00:00+02
用户
d1166a84-ab66-11e8-98d0-529269fb1459
在2018-08-28 00:00:00+02
图形化显示
In the same fashion you can create a MULTIPOINT
using ST_Collect
: 您可以通过相同的方式使用
ST_Collect
创建MULTIPOINT
:
SELECT userId, creationDateTime, ST_AsText(ST_Collect(shape))
FROM locations
GROUP BY userId, creationDateTime
ORDER BY creationDateTime;
userid | creationdatetime | st_astext
--------------------------------------+------------------------+-------------------------------------------------
d1166a84-ab66-11e8-98d0-529269fb1459 | 2018-08-28 00:00:00+02 | MULTIPOINT(-2.22 53.48,-0.11 51.51)
d1166a84-ab66-11e8-98d0-529269fb1459 | 2018-08-29 00:00:00+02 | MULTIPOINT(-1.25 51.75,-1.15 52.96,-0.13 50.82)
(2 Zeilen)
EDIT - Create a set of LINESTRINGS
per day for each user ( MULTILINESTRING
) using CTE
(aka WITH Clause): 编辑 -使用
CTE
(又称为WITH子句)为每个用户每天创建一组LINESTRINGS
( MULTILINESTRING
):
WITH j AS (
SELECT userId, creationDateTime, ST_MakeLine(shape) AS shape
FROM locations
GROUP BY userId, creationDateTime)
SELECT userId, ST_AsText(ST_Collect(shape))
FROM j
GROUP BY userId
userid | st_astext
--------------------------------------+----------------------------------------------------------------------------------
d1166a84-ab66-11e8-98d0-529269fb1459 | MULTILINESTRING((-2.22 53.48,-0.11 51.51),(-1.25 51.75,-1.15 52.96,-0.13 50.82))
(1
Basically what you have to do is to group the records you need (in this case user and date) and use the aggregate function of your choice, eg ST_MergeLine
, ST_Collect
, ST_Union
, ST_Multi
, etc.. 基本上,您要做的是将所需的记录(在这种情况下为用户和日期)进行分组,并使用您选择的聚合函数,例如
ST_MergeLine
, ST_Collect
, ST_Union
, ST_Multi
等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.