Как динамически объединять результаты нескольких агрегированных запросов? - PullRequest
0 голосов
/ 01 февраля 2020

Я создаю запрос Postgres, который должен вызывать агрегатную функцию для каждой записи в массиве, а затем объединять все эти агрегатные значения вместе.

Вот запрос для одного из агрегатов:

WITH mvtdata AS
(
  SELECT ST_AsMVTGeom(geom, ST_TileEnvelope(12,513,412)) AS geom, name, description
  FROM feature
  WHERE feature_set = 'river'
    AND ST_Intersects(geom, ST_TileEnvelope(12,513,412))
)
SELECT ST_AsMVT(mvtdata.*, 'river')
FROM mvtdata;

У меня есть отдельная таблица, которая определяет различные слои данных. Каждый слой данных должен вызывать вышеуказанный запрос и объединять его результаты.

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

|  name        |
|  'river'     |
|  'building'  |

Я хочу вызвать вышеуказанный запрос один раз для каждой записи в таблице и объединить значения. Что-то вроде:

WITH riverdata AS
(
  SELECT ST_AsMVTGeom(geom, ST_TileEnvelope(12,513,412)) AS geom, name, description
  FROM feature
  WHERE feature_set = 'river'
    AND ST_Intersects(geom, ST_TileEnvelope(12,513,412))
),
buildingdata AS
(
  SELECT ST_AsMVTGeom(geom, ST_TileEnvelope(12,513,412)) AS geom, name, description
  FROM feature
  WHERE feature_set = 'building'
    AND ST_Intersects(geom, ST_TileEnvelope(12,513,412))
)
SELECT (ST_AsMVT(riverdata.*, 'river') || ST_AsMVT(buildingdata.*, 'building')) mvt
FROM riverdata, buildingdata;

Как мне написать свой запрос, чтобы использовать такую ​​таблицу (или массив) для динамического объединения произвольного числа слоев данных? Для каждого уровня важно иметь отдельный вызов ST_AsMVT().

1 Ответ

1 голос
/ 01 февраля 2020

Вы можете просто поместить значения ключей в класс IN, чтобы вы могли получить все нужные записи одним запросом. После этого получите записи, полученные с помощью CTE и примените функцию ST_AsMVT.

WITH mvtdata AS
(
  SELECT 
    ST_AsMVTGeom(geom, ST_TileEnvelope(12,513,412)) AS geom, 
    name, description,feature_set
  FROM feature
  WHERE feature_set IN ('river','building')
    AND ST_Intersects(geom, ST_TileEnvelope(12,513,412))
)
SELECT 
  ST_AsMVT(mvtdata.*,feature_set)
FROM mvtdata

Если вы предпочитаете работать с массивами, замените IN на ANY/SOME , например:

WHERE feature_set = ANY ('{river,building}')

Если это все еще не помогает вам, возможно, было бы интересно взглянуть на plpgsql:

CREATE OR REPLACE FUNCTION public.concat_mvt(arr_feature TEXT[]) 
RETURNS BYTEA LANGUAGE plpgsql 
AS $BODY$
DECLARE 
  i INTEGER;
  res BYTEA DEFAULT '';
  rec BYTEA;
BEGIN 
FOR i IN 1..array_length(arr_feature,1) LOOP
  WITH mvtdata AS (
  SELECT 
    ST_AsMVTGeom(geom, ST_TileEnvelope(12,513,412)) AS geom, 
    name, description,feature_set
  FROM feature
  WHERE feature_set = arr_feature[i]
    AND ST_Intersects(geom, ST_TileEnvelope(12,513,412))
  ) SELECT ST_AsMVT(mvtdata.*,arr_feature[i])
    FROM mvtdata INTO rec;
  res := res || rec;
END LOOP;
RETURN res;
END $BODY$;

.. и вызвать функция как это

SELECT concat_mvt('{river,building}')
...