【问题标题】:How to concatenate outputs of multiple aggregate queries dynamically?如何动态连接多个聚合查询的输出?
【发布时间】:2020-02-01 05:37:04
【问题描述】:

我正在构建一个 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() 调用很重要。

【问题讨论】:

    标签: sql postgresql postgis


    【解决方案1】:

    您可以简单地将键值放入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}')
    

    【讨论】:

    • 感谢您的回答,但这并不是我所需要的。我需要使用|| 将多个ST_AsMVT() 调用连接在一起。重要的是每个数据层都是一个单独的 ST_AsMVT() 调用,具有自己的名称,因此 'river-building 将不起作用。
    • @TannerSemerad 我明白了。将river-building 更改为feature_set 对您也不起作用? 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
    • @TannerSemerad 我的一个项目遇到了类似的问题,我想知道您是否找到了比我两天前添加的功能更优雅的解决方案。如果您设法避免编写函数,我会非常感兴趣:) 干杯
    • 该功能对我有用(有一些针对特定问题的更改),但您之前的建议没有。 || 运算符至关重要。非常感谢您发布该功能。关于更优雅的解决方案,我看到string_agg() 作为一个聚合函数,基本上对每个条目执行||。我在这里看到了一个例子,但我自己还没有尝试过:gist.github.com/nyurik/4689ec33d5a8e7713c65c29127c4e968 这个特定的例子看起来比我从你的答案中修改的函数更复杂,所以在我的例子中,函数可能更优雅。再次感谢!
    • @TannerSemerad 这是个好消息,我很高兴它可以帮助你:) 我也研究了纯 SQL 解决方案,但在我看来,它们比我们用 PL/pgSQL 编写的任何东西都复杂.来自德国的欢呼声
    猜你喜欢
    • 2011-09-23
    • 2023-03-28
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多