简体   繁体   English

如何通过两列聚合多个点并从中创建一个LineString / MultiLineString

[英]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_MakeLineGROUP 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-529269fb14592018-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子句)为每个用户每天创建一组LINESTRINGSMULTILINESTRING ):

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_MergeLineST_CollectST_UnionST_Multi等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM