Vous n'êtes pas identifié(e).
Pages : 1
Bonjour. J'ai un soucis sur une requête conditionnelle que je ne parviens pas à réaliser. Voici mon cas : Je souhaite créer une vue qui contient des information de plusieurs tables, dans 2 bases de données (avec un dblink).
Tout fonctionne, sauf que le résultat n'est pas celui que j’attends : j'ai 40 communes, dans lesquelles je souhaite faire apparaitre, pour l'ensemble des communes, les informations souhaitées. Dans cet exemple, je veux faire apparaitre la somme des longueurs de tronçon d'autoroute, par commune. Seulement, toutes mes communes ne sont pas traversées par l'autoroute. Résultat lorsque j'applique cette requête, apparaissent seulement les information sur les communes qui ont une longueur totale > 0. Pour els autres communes, je perd tous les enregistrements.
CREATE OR REPLACE VIEW view_test3
AS SELECT
id,
geom,
code_insee,
long_voirie_a
FROM
info_com,
dblink('hostaddr=xxx port=xxx dbname=xxx user=xxx password=xxx', 'select code_insee, sum("long_carto_troncon") FROM bd_adresse WHERE "domanialite" = ''Autoroute'' GROUP BY code_insee ORDER BY code_insee')as foo (code integer, long_voirie_a double precision )
WHERE
code_insee=foo.code
GROUP BY
code_insee, id, geom, commune, long_voirie_a
;
J'ai donc essayé avec un SELECT CASE, de la manière suivante :
CREATE OR REPLACE VIEW view_test3
AS SELECT
id,
geom,
code_insee,
long_voirie_a,
CASE
WHEN long_voirie_a <> 0 THEN long_voirie_a
ELSE long_voirie_a = NULL
END
FROM
info_com,
dblink('hostaddr=xxx port=xxx dbname=xxx user=xxx password=xxx', 'select code_insee, sum("long_carto_troncon") FROM bd_adresse WHERE "domanialite" = ''Autoroute'' GROUP BY code_insee ORDER BY code_insee')as foo (code integer, long_voirie_a double precision )
WHERE
code_insee=foo.code
GROUP BY
code_insee, id, geom, commune, long_voirie_a
;
Mais rien à faire, j'ai toujours ce champ qui me contraint à ne garder que les enregistrements qui sont traversés par une autoroute.
Voyez-vous ou j'ai pu commettre une erreur ? Merci beaucoup.
Mouhahahaha ça y est !!
Un grand merci rjuju !!
J'ai ajouté la colonne "priorite" dans ma table SEVESO, avec priorite = 1 where nom = R1 et priorite = 2 where nom = R2
Voici mon code qui fonctionne si ça peut en aider d’autres ...
CREATE OR REPLACE FUNCTION update_rayon_seveso()
RETURNS trigger AS
$BODY$
DECLARE
nb integer;
v_nom character varying;
BEGIN
SELECT COUNT(*),foo.nom INTO nb, v_nom FROM dblink('hostaddr=xxxxxx port=xxxxxx dbname=xxxxxx user=postgres password=xxxxxx', 'SELECT wkb_geometry, nom, priorite FROM seveso')
AS foo (geom geometry, nom character varying, priorite integer)
WHERE ST_contains (foo.geom, NEW.wkb_geometry)
GROUP BY foo.nom, foo.priorite
HAVING count(*) > 0
ORDER BY priorite
LIMIT 1;
IF (nb IS NULL) THEN
NEW."5_rayon_seveso" = 'Aucun';
ELSE
NEW."5_rayon_seveso" = v_nom;
END IF ;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION update_rayon_seveso() OWNER TO postgres;
CREATE TRIGGER update_rayon_seveso
BEFORE INSERT OR UPDATE
ON etab
FOR EACH ROW
EXECUTE PROCEDURE update_rayon_seveso();
Merci encore !!
Je pensais à une solution qui serait la suivante :
Lorsque un établissement est dans plusieurs rayons (R1 et R2), alors je pourrais récupérer la géométrie des polygones A et B, les comparer, et retourner le nom du rayon le plus petit des 2.
Ou autrement, lorsqu'un établissement est contenu dans la géométrie d'un rayon R1 (et dans la géométrie d'un rayon R2), alors retourner le nom R1.
Le soucis est que je ne parviens pas à mettre cela en pratique ...
Parfait ! merci beaucoup, cela fonctionne bien pour la plupart de mes cas.
Mais j'ai un cas particulier que je n'arrive pas à résoudre.
J'ai un établissement qui peut être situé :
- dans un rayon R1 (petit rayon avec la géométrie A) donc dans un rayon R2 (c'est le rayon R1 élargi, avec la géométrie B) --> l'étab est contenu dans A et B
- dans un rayon R2 uniquement (il est dans le grand cercle mais pas dans le petit) --> l'étab est contenu dans B uniquement
Pour chacun, je voudrais mettre en place un trigger qui me récupère le nom de la géométrie du rayon selon l'emplacement de l'établissement par rapport à ces rayons :
-- Si l'étab est dans R2 et dans R1 --> "5_rayon" = 'R1' (R1 est prioritaire sur R2)
-- Si l'étab est dans R2 mais pas dans R1 --> "5_rayon" = 'R2'
-- Si l'étab n'est dans aucun rayon --> "5_rayon" = 'Aucun'
Voici ce que j'ai mis en place pour le moment :
-- Function: update_rayon_seveso_test()
-- DROP FUNCTION update_rayon_seveso_test();
CREATE OR REPLACE FUNCTION update_rayon_seveso_test()
RETURNS trigger AS
$BODY$
DECLARE
nb integer;
v_nom character varying;
BEGIN
SELECT COUNT(*),foo.nom INTO nb, v_nom FROM dblink('hostaddr=xxxxxx port=xxxx dbname=xxxxx user=postgres password=xxxxx', 'SELECT wkb_geometry, nom FROM seveso')
AS foo (geom geometry, nom character varying)
WHERE ST_contains (foo.geom, NEW.wkb_geometry)
GROUP BY foo.nom;
IF (nb =0) THEN
NEW."5_rayon_seveso" = 'Aucun';
ELSE
NEW."5_rayon_seveso" = v_nom;
END IF ;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION update_rayon_seveso_test() OWNER TO postgres;
CREATE TRIGGER update_rayon_seveso_test
BEFORE INSERT OR UPDATE
ON etab
FOR EACH ROW
EXECUTE PROCEDURE update_rayon_seveso_test();
Le soucis avec cela est que lorsque un établissement est compris dans un rayon, peu importe lequel, il me renvoi "R2". Lorsqu'un établissement n'est pas dans un rayon, rien n'est ajouté dans la colonne lors de la création d'un point.
Voyez-vous ou je veux en venir, et ou pourrait être mon erreur ?
Merci bien
J'ai opté pour une solution temporaire plus simple mais moins "propre" : Elle consiste à récupérer directement la géométrie de mes zones sans passer par un lien avec une autre table.
L'inconvénient pour le moment, c'est que si je modifie mes zones, ou si j'en ajoute, alors mon trigger sera obsolète ... et il faudra le refaire.
Autre inconvénient : pour des Rayons SEVESO, j'ai une trentaine de rayons ... donc 30 ELSE IF ...
CREATE OR REPLACE FUNCTION update_rayon_pprt()
RETURNS trigger AS
$BODY$
BEGIN
IF ST_within (NEW.wkb_geometry,'0103000020AB6B...') = TRUE THEN
NEW."5_rayon_pprt" = '1';
ELSEIF ST_within (NEW.wkb_geometry,'0103000020A...') = TRUE THEN
NEW."5_rayon_pprt" = '1';
ELSEIF ST_within (NEW.wkb_geometry,'0103000020AB6B...') = TRUE THEN
NEW."5_rayon_pprt" = '1';
ElSE
NEW."5_rayon_pprt" = '0';
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION update_rayon_pprt() OWNER TO postgres;
Mais ça fonctionne, pour le moment, ça me dépanne.
Bonjour,
J'ai un soucis dans l'application d'un trigger.
Dans une table ETAB, je souhaite mettre à jour un de mes champs "5_rayon_ppi" = 1 ou 0 selon que mon établissement soit situé dans un des rayon PPI ou non.
J'ai les géométries des rayons PPI dans une autre base de données.
Voici mon code :
-- Function: update_rayon_ppi()
-- DROP FUNCTION update_rayon_ppi();
CREATE OR REPLACE FUNCTION update_rayon_ppi()
RETURNS trigger AS
$BODY$
BEGIN
SELECT foo.wkb_geometry, new.wkb_geometry
FROM etab, dblink('hostaddr=XXXXX port=XXXXX dbname=mabase user=postgres password=XXXXX', 'SELECT wkb_geometry FROM ppi')
AS foo (wkb_geometry geometry);
NEW."5_rayon_ppi" = '1'
WHERE ST_contains (foo.wkb_geometry, NEW.wkb_geometry);
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION update_rayon_ppi() OWNER TO postgres;
-- Trigger: update_rayon_pprt on etab
-- DROP TRIGGER update_rayon_pprt ON etab;
CREATE TRIGGER update_rayon_ppi
BEFORE INSERT OR UPDATE
ON etab
FOR EACH ROW
EXECUTE PROCEDURE update_rayon_ppi();
Le trigger est executé, mais lorsque je met à jour une donnée dans ma table etab, j'ai le message d'erreur suivant :
---------------------------
pgAdmin III
---------------------------
Une erreur s'est produite :
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function "update_rayon_ppi" line 4 at SQL statement
Etant novice en la matière, je sollicite votre aide afin de pouvoir résoudre ce problème.
Merci à tous
Pages : 1