【问题标题】:How to perform query on two unrelated tables如何对两个不相关的表执行查询
【发布时间】:2021-03-25 19:15:48
【问题描述】:

我有一个table AIdGeometry

还有Temporary table B

Temporary table B 的每个几何图形在 Table A 中都有相交几何图形。我想找到相交的几何图形并合并几何图形。最终表的 id 应该是 Table A,它有交集和几何的并集。如果有超过 1 个相交几何体,则选择任何一个。

我不能在这里执行连接,因为这些表之间没有公共列,所以不知道如何得到最终结果。

【问题讨论】:

    标签: sql postgresql postgis


    【解决方案1】:

    在演示中,我使用类型intrange 来模拟类型geometry。范围足够接近以获得相同的查询:

    demo:db<>fiddle

    SELECT DISTINCT ON (b.id)       -- 3
        a.id,
        a.geom + b.geom             -- 2
    FROM a
    JOIN b ON a.geom && b.geom      -- 1
    
    1. 加入条件应该是检查交叉点。对于范围,它是 &amp;&amp; 运算符,在您的情况下它应该是 st_intersects(a.geom, b.geom)
    2. 合并两个几何。这里是使用 + 运算符完成的,在你的情况下它应该是 st_union(a.geom, b.geom)
    3. DISTINCT ON(b.id) 确保每个 b.id 只有一条记录

    因此,您的最终查询应如下所示:

    SELECT DISTINCT ON (b.id)                    -- 3
        a.id,
        st_union(a.geom, b.geom)                 -- 2
    FROM a
    JOIN b ON st_intersects(a.geom, b.geom)      -- 1
    

    【讨论】:

    • 根据 OP 的要求, a.id 的值不一定不同。 OP 说,如果 temp_table_B 中的几何与 table_A 中的几何相交,则应保留单个 a.id。但是,如果 table_A 中的几何图形与 temp_table_B 的多个几何图形相交怎么办?
    • 你是对的。它必须是 DISTINCT ON (b.id)
    • @S-Man 但 b 没有列 ID。
    • 您的表中应该始终有一个标识符!但是,您可以使用 row_number() 窗口函数轻松生成一个:dbfiddle.uk/…
    • @S-Man 说得好。不幸的是,当我将 row_number 与 st_dump 结合使用时,它会为所有人生成相同的 id。 SELECT row_number() OVER () as id,(st_dump(ST_GeomFromText('MULTILINESTRING((-29 -27,-30 -29.7,-36 -31,-45 -33),(-45 -33,-46 -32) ))'))).geom
    【解决方案2】:

    我想下面的 SQL 会起作用:

    SELECT a.id, ST_UNION(a.geometry, b.geometry) 
    FROM table_A as a, temp_table_B as b 
    WHERE ST_INTERSECTS(a.geometry, b.geometry) 
    

    您可以将结果分组以处理多个交叉点。

    【讨论】:

    • 不符合最后一个要求。如果有的话,它会返回两个联合。
    • OP 不清楚如何处理多个交叉点。如果 table_A 中的几何与 temp_table_B 中的多个几何相交怎么办? OP 仅说明在相反情况下会发生什么(如果来自 temp_table_B 的几何与来自 table_A 的多个几何相交,则保留来自 table_A 的单个 id)。所以我把主逻辑贴出来,OP可以根据自己的需要编辑。
    【解决方案3】:

    如果数据集不是那么大并且几何值遵循与上面显示的相同模式,您可以查看此解决方案

    WITH a AS (
        SELECT 1 AS id
              , 'LineAB' AS geometry
        UNION ALL
        SELECT 2
             , 'LineDE'
        UNION ALL
        SELECT 3
             , 'LineFG'
        UNION ALL
        SELECT 4
             , 'LineXY' )
             
    , temp_b AS (
        SELECT 'LineBC' AS geometry
        UNION ALL
        SELECT 'LineCD'
        UNION ALL
        SELECT 'LineEF' )
        
    , a_last AS (
        SELECT a.id
             , a.geometry
             , RIGHT(a.geometry, 1) AS a_key            -- get the last symbol for further join with temp_b
          FROM a )
    , a_nlast AS (
        SELECT a.id
             , a.geometry
             , SUBSTRING(a.geometry, 5, 1) AS a_key
          FROM a )
    , b_nlast AS (
        SELECT temp_b.geometry
             , SUBSTRING(temp_b.geometry, 5, 1) AS b_key        -- get one symbol before the last symbol for further join with a table
          FROM temp_b )
    , b_last AS (
        SELECT temp_b.geometry
             , RIGHT(temp_b.geometry, 1) AS b_key
          FROM temp_b )
    -- try all possible combinations of last and not last sybols from both tables
    SELECT a_last.id
         , CONCAT('Union (', SUBSTRING(a_last.geometry, 5, 2), '+', SUBSTRING(b_nlast.geometry, 5, 2), ')') 
      FROM a_last JOIN b_nlast ON a_last.a_key = b_nlast.b_key
    UNION ALL 
    SELECT a_last.id
         , CONCAT('Union (', SUBSTRING(a_last.geometry, 5, 2), '+', SUBSTRING(b_last.geometry, 5, 2), ')') 
      FROM a_last JOIN b_last ON a_last.a_key = b_last.b_key
    UNION ALL
    SELECT a_nlast.id
         , CONCAT('Union (', SUBSTRING(a_nlast.geometry, 5, 2), '+', SUBSTRING(b_last.geometry, 5, 2), ')') 
      FROM a_nlast JOIN b_last ON a_nlast.a_key = b_last.b_key
    UNION ALL
    SELECT a_nlast.id
         , CONCAT('Union (', SUBSTRING(a_nlast.geometry, 5, 2), '+', SUBSTRING(b_nlast.geometry, 5, 2), ')') 
      FROM a_nlast JOIN b_nlast ON a_nlast.a_key = b_nlast.b_key;
    

    此解决方案从给定模式中获取某些符号并尝试不同的组合以形成所有可能组合的列表。

    问题是关于 ids 的。据说它应该从一个表中获取 id,但如果您希望它是唯一的,最好创建一个单独的表,您可以在其中放置带有自己唯一 id 的结果组合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      • 2019-11-11
      • 2021-03-25
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      相关资源
      最近更新 更多