Как объединить несколько точек по двум столбцам и создать из них LineString / MultiLineString - PullRequest
0 голосов
/ 29 августа 2018

У меня есть таблица с названием локации, в которой есть эти строки:

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)

Представьте, что в этом столбце shape в моей таблице в часах регистрируется число пользователей. Когда регистрируется время этой точки, которая зарегистрирована в таблице, сохраняется в столбце creationDateTime, например, 2018-08-22 00:03:41.649+04:30.

Как мне извлечь эту информацию:

each User ---- each day ---- list of geometry(shape column) в примере:

Пользователь 1 в первый день имеет список геометрических точек. У пользователя 1 во второй день есть список геометрических точек и так далее ...

Я сделал этот запрос Монго для того же проекта:

{$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}
 }

Но как я могу сделать это с postgresql? На postgre такого рода агрегации не существует, и я новичок на postgresql. Это мой запрос:

(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")

Этот запрос не подходит, и я знаю, что у этого запроса есть проблема. deviceId пользователей, часто повторяющихся с другой строкой. Как я могу справиться с этим?

В конце я хочу создать многополую линию per user - per day - multi poly line

1 Ответ

0 голосов
/ 29 августа 2018

Вероятно, есть миллион способов ответить на этот вопрос. Вот один из них:

Учитывая вашу структуру таблицы ..

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);

.. И эти образцы данных ..

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)');

.. Вы можете объединить баллы за пользователя + дату и создать LINESTRING, используя ST_MakeLine с GROUP BY:

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)

Графическое изображение пользователя d1166a84-ab66-11e8-98d0-529269fb1459 при 2018-08-28 00:00:00+02 enter image description here

Таким же образом вы можете создать MULTIPOINT, используя ST_Collect:

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)

enter image description here

РЕДАКТИРОВАТЬ - Создать набор LINESTRINGS в день для каждого пользователя (MULTILINESTRING), используя CTE (он же WITH WITH):

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 

enter image description here

По сути, вам нужно сгруппировать нужные записи (в данном случае пользователя и даты) и использовать функцию агрегирования по вашему выбору, например, ST_MergeLine, ST_Collect, ST_Union, ST_Multi и т. Д.

...