8 votos

Cambio de geometría de tabla búfer dinámicamente en PostGIS usando SQL simple

Tengo dos tablas en PostGIS, un punto y un point_buffer tabla. El punto de la tabla tiene un buffer_distance campo, con un valor predeterminado decir 200. Ahora quiero cambiar el buffer de la tabla de geometría cada vez que me cambio la buffer_distance valor en mi punto de tabla. Puedo hacer esto por una sola fila en mi point_buffer tabla con la siguiente:

UPDATE point_buffer
SET the_geom = (SELECT ST_Buffer(the_geom,500) FROM point WHERE gid = 1)
FROM point
WHERE point.gid = point_buffer.gid

Pero siempre estoy tratando de cambiar el conjunto de point_buffer tabla (goteo de la cláusula where en mi sub-consulta) obtengo el mensaje de error:

'ERROR: más de una de las filas devueltas por una subconsulta utilizado como un la expresión'.

Mi pregunta es, puedo cambiar todo el point_buffer tabla de una sola vez? Sé que una opción es usar una para la lopp, con el límite superior, siendo el valor de recuento de mi tabla de puntos de e incrementando el punto.gid valor . Pero yo quiero hacer esto en la llanura de SQL.

6voto

tobes Puntos 19

Debe trabajar si quiere cambiar todos los búferes a 500:

Tal vez una vista tendría más sentido, que realmente sería dinámica, no hay actualizaciones necesarias:

6voto

Deeksy Puntos 2084

Usted puede utilizar un punto de vista, pero también se puede utilizar desencadenadores para actualizar automáticamente el búfer de tabla cuando se modifica el punto original de la tabla. Esto es realmente útil si usted no quiere regenerar los búferes cada vez que la vista de su mesa, como búfer de cálculo es un uso intensivo de la cpu de tareas.

He aquí un ejemplo de código que lo implementa : una tabla de puntos y un point_buffer tabla que se actualiza automáticamente basándose en el punto modificaciones de la tabla.

Puedes probar con QGIS : abra las dos tablas, entrar en modo de edición en la tabla de puntos. Mover un punto o cambiar el buffer_distance valor, y cada vez que se guarda, el buffer será actualizado.

disfrutar :)

drop table if exists point;
create table point (
    gid serial primary key
    , point_name varchar
    , buffer_distance double precision
    , the_geom geometry
);

drop table if exists point_buffer;
create table point_buffer (
    gid serial primary key
    , point_gid integer
    , the_geom geometry
);

select populate_geometry_columns();

insert into 
    point (point_name, buffer_distance, the_geom) 
select
    'point ' || n::varchar as point_name
    , random() * 100 + min_buf as buffer_distance
    , st_setsrid(st_point(random() * 10000 + x0, random() * 10000 + y0), 2154) as the_geom
from
        generate_series(1, 1000) as n
        , (values (10)) as foox(x0)
        , (values (10)) as fooy(y0)
        , (values (10)) as buf(min_buf);

-- insert values into point_buffer
insert into
    point_buffer (point_gid, the_geom)
select
    gid as point_gid
    , st_buffer(the_geom, buffer_distance)
from
    point;

-- update all point_buffer
update
    point_buffer as pb
set
    the_geom = st_buffer(p.the_geom, p.buffer_distance)
from
    point as p
where
    p.gid = pb.point_gid;

-- add trigger to automate insert / delete / update
create or replace function update_point_buffer() returns trigger as
$$
begin
    -- delete
    IF (TG_OP = 'DELETE') THEN
        delete from point_buffer as pb where point_gid = OLD.gid;
        return OLD;
    -- insert
    ELSIF (TG_OP = 'INSERT') THEN
        insert into
            point_buffer (point_gid, the_geom)
        select
            NEW.gid as point_gid
            , st_buffer(NEW.the_geom, NEW.buffer_distance);
        return NEW;
    -- update
    else
        update
            point_buffer as pb
        set
            the_geom = st_buffer(NEW.the_geom, NEW.buffer_distance)
        where
            pb.gid = NEW.gid;
        return NEW;
    END IF;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_point_point_buffer ON point;
CREATE TRIGGER trg_point_point_buffer AFTER DELETE OR INSERT OR UPDATE ON point
    FOR EACH ROW EXECUTE PROCEDURE update_point_buffer();

/* use it */

-- insert
insert into 
    point (point_name, buffer_distance, the_geom)
select
    'added point to test trigger' as point_name
    , random() * 100 + min_buf as buffer_distance
    , st_setsrid(st_point(random() * 10000 + x0, random() * 10000 + y0), 2154) as the_geom
from
        (values (10)) as foox(x0)
        , (values (10)) as fooy(y0)
        , (values (10)) as buf(min_buf);

select
    st_astext(pb.the_geom)
    , *
from 
    point_buffer as pb
join
    point as p
on
    p.gid = pb.point_gid
where
    p.point_name = 'added point to test trigger';

-- update
update 
    point as p
set
    the_geom = st_setsrid(st_point(0, 0), 2154)
    , buffer_distance = 1
where
    p.point_name = 'added point to test trigger';

-- check point_buffer
select
    st_astext(pb.the_geom)
    , *
from 
    point_buffer as pb
join
    point as p
on
    p.gid = pb.point_gid
where
    p.point_name = 'added point to test trigger';

-- delete
delete from
    point as p
where
    p.point_name = 'added point to test trigger';

-- check point_buffer
select
    *
from
    point_buffer as pb
where
    point_gid = 1001;

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X