触发器postgresql中的距离计算

时间:2018-09-11 12:36:30

标签: sql postgresql postgis

我有两个表“ modulo1_cella”和“ modulo2_campionamento”。

第一个“ modulo1_cella”包含多边形,而第二个“ modulo2_campionamento”包含点(样本)。现在,我需要为每个多边形分配最近的采样,以及采样器本身的标识。

                                           Table "public.modulo1_cella"
      Column       |       Type        |                            Modifiers
-------------------+-------------------+------------------------------------------------------------------
 cella_id          | integer           | not null default nextval('modulo1_cella_cella_id_seq'::regclass)
 nome_cella        | character varying |
 geometria         | geometry          |
 campione_id       | integer           |
 dist_camp         | double precision  |

                                       Table "public.modulo2_campionamento"
          Column          |            Type             |                                    Modifiers
--------------------------+-----------------------------+----------------------------------------------------------------------------------
 campione_id              | integer                     | not null default nextval('modulo2_campionamento_aria_campione_id_seq'::regclass)
 x_campionamento          | double precision            |
 y_campionamento          | double precision            |
 codice_campione          | character varying(10)       |
 cella_id                 | integer                     |
 geometria                | geometry(Point,4326)        |

我正在寻找INSERT / UPDATE触发器,该触发器对于“ modulo1_cella”表的每一行(即对于每个多边形)均返回:

  • 最近的样本“ campione_id”;
  • 相应的距离“ dist_camp”。

我创建了一个有效的查询,但无法将其转换为触发器。

CREATE TEMP TABLE TemporaryTable 
(
    cella_id int,
    campione_id int,
    distanza double precision 
);

INSERT INTO TemporaryTable(cella_id, campione_id, distanza)
SELECT 
DISTINCT ON (m1c.cella_id) m1c.cella_id, m2cmp.campione_id, ST_Distance(m2cmp.geometria::geography, m1c.geometria::geography)  as dist

FROM modulo1_cella As m1c, modulo2_campionamento As m2cmp  
WHERE ST_DWithin(m2cmp.geometria::geography, m1c.geometria::geography, 50000) 
ORDER BY m1c.cella_id, m2cmp.campione_id, ST_Distance(m2cmp.geometria::geography, m1c.geometria::geography);

UPDATE modulo1_cella as mc
SET campione_id=tt.campione_id, dist_camp=tt.distanza
from TemporaryTable as tt
where tt.cella_id=mc.cella_id;

DROP TABLE TemporaryTable;

有帮助吗?预先谢谢你。

1 个答案:

答案 0 :(得分:0)

首先,如果“ geometria”不是geography,而是geometry,则应在表上将其设置为geography类型。

ALTER TABLE modulo2_campionamento
  ALTER COLUMN geometria
  SET DATE TYPE geography(POINT 4326)
  USING (geometria::geography);

ALTER TABLE modulo1_cella
  ALTER COLUMN geometria
  SET DATA TYPE geography(4326)
  USING (geometria::geography);
  

现在,我需要为每个多边形分配最近的采样,以及采样器本身的标识。

您通常不会这样做,因为使用KNN search anyway.

可以很快找到最近的样本
CREATE INDEX ON modulo1_cella USING gist (geometria);
CREATE INDEX ON modulo2_campionamento USING gist (geometria);
VACUUM FULL ANALYZE modulo1_cella;
VACUUM FULL ANALYZE modulo2_campionamento;

SELECT *
FROM modulo1_cella As m1c
CROSS JOIN LATERAL (
  SELECT *
  FROM modulo2_campionamento As m2cmp
  WHERE ST_DWithin(m2cmp.geometria, m1c.geometria, 50000)
  ORDER BY m2cmp.geometria <-> m1c.geometria, 
    m1c.cella_id,
    m2cmp.campione_id
  FETCH FIRST ROW ONLY
) AS closest_match

这比您编写的DISTINCT ON查询要快

如果那足够快,我建议使用VIEW。如果那还不够快,我建议使用MATERIALIZE VIEW。如果仍然不够快,您的工作量将非常小,可能值得研究使用触发器的解决方案。但只有那样。