Получить значение каждой последней записи, сгруппированной по идентификатору - PullRequest
0 голосов
/ 07 мая 2019

У меня есть таблица записей данных, которые хранятся с течением времени, примерно так:

|| ID || timestamp || position || value || field1 || field2 ||

И еще одна таблица, представляющая географические точки, примерно так:

|| ID || position || field1 || field2 ||

Где field1 и field2 каждой таблицы находятся в одной категории (что позволяет мне сравнивать их)

У меня есть запрос, который дает мне самую близкую точку (из таблицы точек) к каждой записи, выглядя так:

SELECT B.ID, A.timestamp as date, A.value, A.field1, A.field2
FROM (SELECT DISTINCT ON (ID) * FROM records) AS A
CROSS JOIN LATERAL (SELECT *
                    FROM points
                    ORDER BY A.position <-> geom
                    LIMIT 1) AS B
WHERE A.field1 = B.field1
AND A.field2 = B.field2

Что позволяет мне точно знать, из какой точки исходит значение записи.

Мне нужно получить последнее значение для каждой точки, и я начал так:

SELECT B.ID, MAX(A.timestamp) as date, A.field1, A.field2
FROM (SELECT DISTINCT ON (ID) * FROM records) AS A
CROSS JOIN LATERAL (SELECT *
                    FROM points
                    ORDER BY A.position <-> geom
                    LIMIT 1) AS B
WHERE A.field1 = B.field1
AND A.field2 = B.field2
GROUP BY B.ID, A.field1, A.field2

Но я не знаю, как получить значение из записей данных в моем наборе результатов, сейчас, если я просто добавлю его сверху, он попросит добавить его в GROUP BYпункт.

В других ответах я читал, что мне нужно использовать INNER JOIN или LATERAL JOIN, но в этом случае он ищет ближайшую точку каждой записи в секунду и значительно замедляет запрос.Есть ли способ избежать выполнения запроса два раза, а затем сопоставить их, используя field1 и field2?

EDIT:

Вот как выглядят записи данных (позиция действительно длинная и не релевантнаяпоэтому я решил не показывать их)

ID  |      timestamp      |   position   | value |   field1   |  field2
----|---------------------|--------------|-------|------------|-----------
001 | 2019-05-03 17:50:00 |    {....}    |   5   |   South    |  Forward
----|---------------------|--------------|-------|------------|-----------
002 | 2019-05-03 17:55:00 |    {....}    |  17   |   South    |  Forward
----|---------------------|--------------|-------|------------|-----------
003 | 2019-05-03 18:30:00 |    {....}    |   0   |   South    |  Backward
----|---------------------|--------------|-------|------------|-----------
004 | 2019-05-03 13:20:00 |    {....}    |  25   |    West    |  Forward
----|---------------------|--------------|-------|------------|-----------
005 | 2019-05-03 14:30:00 |    {....}    |  36   |    West    |  Backward
----|---------------------|--------------|-------|------------|-----------
006 | 2019-05-03 16:00:00 |    {....}    |  12   |    West    |  Backward

После выполнения моего первого запроса (чтобы получить ближайшую точку) я получаю это:

 B.ID |      timestamp      | value |   field1   |  field2
------|---------------------|-------|------------|-----------
 475  | 2019-05-03 17:50:00 |   5   |   South    |  Forward
------|---------------------|-------|------------|-----------
 263  | 2019-05-03 17:55:00 |  17   |   South    |  Forward
------|---------------------|-------|------------|-----------
 157  | 2019-05-03 18:30:00 |   0   |   South    |  Backward
------|---------------------|-------|------------|-----------
 957  | 2019-05-03 13:20:00 |  25   |    West    |  Forward
------|---------------------|-------|------------|-----------
 547  | 2019-05-03 14:30:00 |  36   |    West    |  Backward
------|---------------------|-------|------------|-----------
 547  | 2019-05-03 16:00:00 |  12   |    West    |  Backward

Где B.ID соответствуетближайшая точка к позиции записи.

То, что я получаю при выполнении запроса для получения последней записи для каждой комбинации [ID / field1 / field2], таково:

 B.ID |      timestamp      |   field1   |  field2
------|---------------------|------------|-----------
 475  | 2019-05-03 17:50:00 |   South    |  Forward
------|---------------------|------------|-----------
 263  | 2019-05-03 17:55:00 |   South    |  Forward
------|---------------------|------------|-----------
 157  | 2019-05-03 18:30:00 |   South    |  Backward
------|---------------------|------------|-----------
 957  | 2019-05-03 13:20:00 |    West    |  Forward
------|---------------------|------------|-----------
 547  | 2019-05-03 16:00:00 |    West    |  Backward

Где выможно увидеть только исчезнувшую перед последней строкой строку, поскольку в ней была та же комбинация, что и в последней строке (ID / field1 / field2), и она была старше.

И мне хотелось бы вот что:

 B.ID |      timestamp      | value |   field1   |  field2
------|---------------------|-------|------------|-----------
 475  | 2019-05-03 17:50:00 |   5   |   South    |  Forward
------|---------------------|-------|------------|-----------
 263  | 2019-05-03 17:55:00 |  17   |   South    |  Forward
------|---------------------|-------|------------|-----------
 157  | 2019-05-03 18:30:00 |   0   |   South    |  Backward
------|---------------------|-------|------------|-----------
 957  | 2019-05-03 13:20:00 |  25   |    West    |  Forward
------|---------------------|-------|------------|-----------
 547  | 2019-05-03 16:00:00 |  12   |    West    |  Backward

1 Ответ

0 голосов
/ 07 мая 2019

Вы просто хотите distinct on снова?

SELECT DISTINCT ON (p.ID) p.ID, r.*
FROM (SELECT DISTINCT ON (r.ID) r.* FROM records r
     ) r CROSS JOIN LATERAL
     (SELECT p.*
      FROM points p
      ORDER BY r.position <-> p.geom
      LIMIT 1
     ) p
WHERE r.field1 = p.field1 AND r.field2 = p.field2
ORDER BY p.ID, r.timestamp DESC;

Я не могу понять, что вы намереваетесь:

(SELECT DISTINCT ON (ID) *
 FROM records
)

Как минимум, вы должны иметь ORDER BY:

(SELECT DISTINCT ON (ID) *
 FROM records
 ORDER BY ID
)

Однако ваши данные образца и имя ID предполагают, что дубликатов нет, поэтому DISTINCT ON может и не понадобиться.

...