PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : Général » Jointure spatiale multiple » 22/11/2018 18:42:58

Bonjour,

Merci pour votre réponse. Effectivement je me demandais si il fallait décomposer la requête pour comparer les tables deux à deux ou si c'était possible autrement. En revanche je ne comprends pas trop quand vous parlez de mettre des parenthèses? Il est possible de faire des condition "imbriquées" avec des parenthèses dans un where?

Pour ce qui est de ma requête, j'en suis venu à bout en apprenant que les CTE pouvaient appeller une CTE précédente. J'ai donc construit mes jointures progressivement deux à deux dans les CTE avec WITH.

WITH
canalisation_piquage AS (
SELECT * FROM papaichton_raepa_canalaep_l_ddd WHERE branchemnt = 'O'
),
canalisation_principale AS (
SELECT * FROM papaichton_raepa_canalaep_l_ddd WHERE branchemnt = 'N'
),
startpoint AS (
SELECT ST_Startpoint(st_linemerge(geom)) as geom FROM papaichton_raepa_canalaep_l_ddd
),
endpoint AS(
SELECT ST_Endpoint(st_linemerge(geom)) as geom FROM papaichton_raepa_canalaep_l_ddd
),
startpoint_endpoint AS (
SELECT * FROM startpoint
UNION
SELECT * FROM endpoint
),
condition0 AS (
SELECT canalisation_piquage.idcana, canalisation_piquage.id, canalisation_principale.idcana, ST_INTERSECTION(canalisation_piquage.geom, canalisation_principale.geom) as geom 
FROM canalisation_piquage, canalisation_principale
WHERE ST_INTERSECTS(canalisation_piquage.geom, canalisation_principale.geom)
)
SELECT * FROM condition0, startpoint_endpoint
WHERE ST_INTERSECTS(condition0.geom, startpoint_endpoint.geom)

Merci pour le coup de main.

#2 Re : Général » Jointure spatiale multiple » 21/11/2018 15:17:08

Merci pour votre réponse.
Pour préciser, je souhaite sélectionner les couples d'identifiants des tables t1 et t2 où les géometries s'intersectent et qui vérifient aussi deux conditions d'intersection sur les géometries des tables t3 et t4.
Je me demandais surtout quelle était la syntaxe correcte pour exprimer la requête présentée ci dessus. Cette formulation est incorrecte, et celle avec des jointures ne renvoie aucun résultat (alors même que des géometries s'intersectant existent. En effet, je ne vois pas comment exprimer un OR avec des jointures, ni comment réaliser une condition spatiale sur quatre tables différentes. Les tables sont de type :
id(integer)  col1(varchar) col2(varchar) col3(varchar) geom(geometry)

La question est vraiment syntaxique, et malgré plusieurs recherches dans des forums j'ai n'ai trouvé personne traitant un problème similaire.

#3 Re : Général » Jointure spatiale multiple » 21/11/2018 14:35:51

Bonjour,

Etant toujours bloqué, je vais reformuler ma question. J'aimerai pouvoir executer une commande du type :

WITH
t1 AS (
SELECT * FROM t01 WHERE x = 'O'
),
t2 AS (
SELECT * FROM t02 WHERE x = 'N'
)
SELECT t1.id, t2.id FROM t1, t2, t3, t4
WHERE ST_INTERSECTS (t1.geom, t2.geom)
AND ST_INTERSECTS (t1.geom, t3. geom)
OR ST_INTERSECTS (t1.geom, t4.geom)

J'ai essayé avec des jointures mais cela ne marche pas non plus... Une bonne âme aurait elle une suggestion?
Merci d'avance.

#4 Général » Jointure spatiale multiple » 13/11/2018 21:04:08

robinson
Réponses : 5

Bonjour,

Je cherche à insérer dans une table les identifiants de certaines lignes sous conditions d'intersection géométrique. Ma table représente des canalisations (lignes) dont certaines, secondaires, ne sont reliées que par un seul côté aux canalisations principales. J'ai besoin de récupérer les identifiants des canalisations principales pour les insérer dans une colonne des canalisations secondaires.
J'ai écrit le code suivant (j'écrirai le UPDATE plus tard) :

WITH
canalisation_secondaire AS (
SELECT * FROM canalisations WHERE branchemnt = 'O'
),
canalisation_principale AS (
SELECT * FROM canalisations WHERE branchemnt = 'N'
)
SELECT canalisation_secondaire.idcana, canalisation_secondaire.id, canalisation_principale.idcana FROM canalisation_secondaire, canalisation_principale
WHERE ST_INTERSECTS(canalisation_secondaire.geom, canalisation_principale.geom)

Néanmoins, certaines lignes se croisent et je récupère donc aussi les identifiants des canalisations principales coupant les canalisations secondaires en leur milieu. J'ai donc essayé de rajouter une contrainte pour ne garder que les identifiants des canalisations en bout de ligne. J'ai donc créé une table temporaire avec des points (st_startpoint et endpoint).
Néanmoins, je n'arrive pas à réaliser une double clause where sur une table extérieure :


WITH
canalisation_secondaire AS (
SELECT * FROM canalisations WHERE branchemnt = 'O'
),
canalisation_principale AS (
SELECT * FROM canalisations WHERE branchemnt = 'N'
)
SELECT canalisation_secondaire.idcana, canalisation_secondaire.id, canalisation_principale.idcana FROM canalisation_secondaire, canalisation_principale 
WHERE ST_INTERSECTS(canalisation_secondaire.geom, canalisation_principale.geom)
AND ST_INTERSECTS(canalisation_secondaire.geom, start_end_point.geom)

La table start_end_point est manquante de la clause FROM, et si je la rajoute j'obtiens le double des résultats attendus

La formulation avec une double jointure ne fonctionne pas non plus (elle renvoie plus d'enregistrements qu'attendu) :

WITH
canalisation_secondaire AS (
SELECT * FROM canalisations WHERE branchemnt = 'O'
),
canalisation_principale AS (
SELECT * FROM canalisations WHERE branchemnt = 'N'
)
SELECT canalisation_secondaire.idcana, canalisation_secondaire.id, canalisation_principale.idcana FROM canalisation_secondaire
LEFT OUTER JOIN canalisation_principale ON ST_INTERSECTS(canalisation_secondaire.geom, canalisation_principale.geom)
LEFT OUTER JOIN endpoint_startpoint ON ST_INTERSECTS(canalisation_secondaire.geom, canalisation_principale.geom)

Idéalement, j'aurais souhaité faire porter la condition sur l'intersection stricte de trois tables. Est-ce possible?
Merci d'avance.

#5 Général » SELECT dynamique sur les Champs avec INFORMATION_SCHEMA.COLUMNS » 22/08/2018 17:54:38

robinson
Réponses : 1

Bonjour,

Je souhaiterai constituer une fonction dynamique (ou une requête simple) me permettant de récupérer les noms des champs d'une table pour les utiliser dans un SELECT. J'ai en effet une table avec un grand nombre de champs, en plus susceptibles de s'incrémenter et j'aimerai ne pas avoir à rajouter manuellement le nom des champs dans mes requêtes à chaque fois.

Je sais que l'on peut récupérer les noms des champs d'une table avec la requête :

 SELECT (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='matable') ; 

Maintenant, j'aimerai concaténer tous les enregistrements du champs ainsi créé (et les formater sous le format 'nomcol1, nomcol2, nomcol3') pour pouvoir les appeler dans un select.
Pour faire un exemple, j'aimerai faire un

 SELECT (SELECT (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='matable')) FROM matable 

Il me semble que c'est possible, vu que j'ai trouvé ce post :

SQLPro a écrit :

" Il faut construire votre requête en assemblant des bouts de chaines de caractères lus à partir des vues de métadonnées comme INFORMATION_SCHEMA.COLUMNS puis exécuter la chaine de caractères avec la commande EXECUTE."

https://www.developpez.net/forums/d1861 … ynamiques/


Mais la méthode n'est malheureusement pas détaillée et je n'ai pas trouvé de fonction sur les chaines de caractères adéquate.
Je vous remercie d'avance si vous avez des pistes pour m'aider.

#6 Re : PL/pgSQL » Analyse sur plusieurs champs » 25/06/2018 15:11:12

J'ai bien compris, je vais essayer de coller au mieux aux règles normales.
Merci pour les précisions!

#7 Re : PL/pgSQL » Analyse sur plusieurs champs » 19/06/2018 21:39:57

Bonjour,

Après plusieurs jours de travail, j'ai suis enfin arrivé à mes fins (bien que tout cela soit un peu lourd... et malheureusement pas dynamique!), avec un petit emprunt aux expressions régulières (clin d'oeil à Marc Cousin qui m'a mis sur la bonne piste avec le PERL).


Tout d'abord, il faut retravailler la table de départ afin de remplacer les valeurs par des codes correspondant à des chaine de caractères de taille égale. Ensuite, il faut créer un attribut concaténant tous les champs visés par l'analyse :

CREATE TABLE position_type AS	
SELECT type05 ||' '|| type06 ||' '|| type07||' '|| type08 ||' '|| type09 ||' '|| type10 ||' '|| type11 ||' '|| type12 ||' '|| type13 ||' '|| type14 ||' '|| type15 ||' '|| type16 AS type_vec

On peut dès lors compter le nombre d’occurrences d'une chaine de caractères dans la chaine de caractères ainsi créée. Pour ce faire, on calcule la longueur de string totale avec CHAR_LENGTH, à laquelle on retranche la longueur de la chaine sans le string recherché (ici 'AF', remplacé par des 'blancs' : ''), ce qui nous donne la dimension de la (répétition de) chaine de caractère recherchée. Il reste alors à diviser la valeur obtenue par la longueur de la chaine de caractère recherchée pour avoir le nombre de répétitions :

ALTER TABLE position_type ADD COLUMN nbre_occurrence NUMERIC;
UPDATE position_type 
SET nbre_occurrence = (CHAR_LENGTH(type_vec) - CHAR_LENGTH(REPLACE(type_vec, 'AF', ''))) 
    / CHAR_LENGTH('AF');

Un fois le nombre d’occurrences obtenu, on peut alors définir le nombre d'attributs à créer (=nombre maximum d'occurences) ensuite pour le calcul des positions des strings recherchés dans la chaine de caractère totale.

SELECT nbre_occurrence FROM position_type GROUP BY nbre_occurrence

Pour ma part, j'ai 4 colonnes à créer :


ALTER TABLE position_type ADD COLUMN position_1 VARCHAR(40), ADD COLUMN position_2 VARCHAR(40), ADD COLUMN position_3 VARCHAR(40), ADD COLUMN position_4 VARCHAR(40);

Il faut ensuite calculer les positions des chaines de caractère grâce à la fonction POSITION. Celle-ci ne donne malheureusement que l'emplacement de la première occurrence, et non pas de toutes, ce qui nous oblige à répéter les instructions en boucle avec un CASE renvoyant sur la colonne précédemment remplie :


UPDATE position_type
SET 
position_1 = POSITION('AF' IN type_vec);
UPDATE position_type
SET 
position_2 = (CASE 
WHEN nbre_occurrence >= 2 THEN 2 + position_1::integer + POSITION('AF' IN substring (type_vec from 3 + position_1::integer))
ELSE 0
END);
UPDATE position_type
SET 
position_3 = (CASE 
WHEN nbre_occurrence >= 3 THEN 2 + position_2::integer + POSITION('AF' IN substring (type_vec from 3 + position_2::integer))
ELSE 0
END);
UPDATE position_type
SET 
position_4 = (CASE 
WHEN nbre_occurrence >= 4 THEN 2 + position_3::integer + POSITION('AF' IN substring (type_vec from 3 + position_3::integer))
ELSE 0
END);

Pour finir, on peut compter le nombre d'années (de champs séparant deux valeurs similaires pour le même enregistrement). J'ai ici écrit la fonction pour calculer directement une moyenne. Je ne détaille pas mais il faut bien prendre en compte les espaces dans le comptage des positions :

ALTER TABLE position_type ADD COLUMN jachere_moy NUMERIC;
UPDATE position_type
SET
jachere_moy = ROUND(
(CASE 
WHEN nbre_occurrence = 2 THEN
(((position_2::numeric - position_1::numeric)/3)-1)/(nbre_occurrence::numeric-1)
WHEN nbre_occurrence = 3 THEN
((((position_2::numeric - position_1::numeric)/3)-1) + (((position_3::numeric - position_2::numeric)/3)-1))/(nbre_occurrence::numeric-1)
WHEN nbre_occurrence = 4 THEN
((((position_2::numeric - position_1::numeric)/3)-1) + (((position_3::numeric - position_2::numeric)/3)-1) + (((position_4::numeric - position_3::numeric)/3)-1))/(nbre_occurrence::numeric-1)
ELSE 0
END)::numeric, 3)

On a donc la distance moyenne entre deux occurrences. Tout cela est très lourd, et surtout pas du tout dynamique (besoin de rajouter plusieurs lignes à chaque ajout d'un attribut dans la table de base).


@ Marc Cousin : Merci pour le script, mais je n'ai pas du tout compris et je ne suis pas en mesure d'apprendre un nouveau language de programmation... Bien qu'on m'aie conseillé PLPgSQL avec un travail sur les information_schema.COLUMNS pour rendre des colonnes dynamiques.
Cette expérience de script m'aura convaincu que PostGreSQL n'est pas fait pour faire de la statistique et je vais essayer de travailler en R ou Pl/R.


@ dverite : merci pour vos commentaires, personne ne m'avait encore faire cette remarque le modèle conceptuel de ma base. J'entends qu'un attribut ne doit pas porter en soi une information, mais qu'elle doit rester dans les valeurs. Si j'ai bien compris votre schéma, on a plusieurs fois le même id dans la table mesure, autant que d'années (avec leur type correspondant)? Quelle serait alors la différence entre le modèle que vous proposez et la table suivante, qui synthétise votre modèle en une seule table en dupliquant par la même occasion les géométries? Aurait-on une perte de performance? :

CREATE TABLE matrice_total_test AS
SELECT type05 AS type, '2005' AS annee, geom FROM matrice_test
UNION
SELECT type06 AS type, '2006' AS annee, geom FROM matrice_test
UNION
SELECT type07 AS type, '2007' AS annee, geom FROM matrice_test
UNION
SELECT type08 AS type, '2008' AS annee, geom FROM matrice_test
UNION
SELECT type09 AS type, '2009' AS annee, geom FROM matrice_test
UNION
SELECT type10 AS type, '2010' AS annee, geom FROM matrice_test
UNION
SELECT type11 AS type, '2011' AS annee, geom FROM matrice_test
UNION
SELECT type12 AS type, '2012' AS annee, geom FROM matrice_test
UNION
SELECT type13 AS type, '2013' AS annee, geom FROM matrice_test
UNION
SELECT type14 AS type, '2014' AS annee, geom FROM matrice_test
UNION
SELECT type15 AS type, '2015' AS annee, geom FROM matrice_test
UNION
SELECT type16 AS type, '2016' AS annee, geom FROM matrice_test
ORDER BY annee ASC geom DESC;
ALTER TABLE matrice_total_test ADD COLUMN id SERIAL PRIMARY KEY

Merci beaucoup pour vos contributions!

#8 PL/pgSQL » Analyse sur plusieurs champs » 11/06/2018 22:24:43

robinson
Réponses : 5

Bonjour,

Tout d'abord merci pour vos contributions à mes questionnements précédents, ça permet d'avancer un peu quand on est tout seul.
Je me demandais si il était possible de réaliser une analyse sur plusieurs colonnes (même si ce n'est pas vraiment le but de postgreSQL) :
J'ai une table avec un grand nombre d'enregistrements et des champs de deux types, un pour caractériser une géométrie et d'autres, tous identiques dans leur structure et les valeurs qu'ils prennent, représentant des évolutions temporelles :


géométrie(polygon) type_année_n(varchar) type_année_n+1(varchar) type_annee_n+2(varchar)


Je souhaiterai construire une fonction visant à compter le nombre "d'années" (= de colonnes) séparant deux valeurs identiques des champs "type".
Par exemple, les valeurs prises par les champs "type" pouvant être type_1, type_2, type_3, pour l'exemple de tableau suivant :


id géométrie(polygon) type_année_n(varchar) type_année_n+1(varchar) type_annee_n+2(varchar)
1   geom                     type_1                         type_2                             type_1
2   geom                     type_1                         type_3                             type_1
3   geom                     type_1                         type_1                             type_2


J'aimerai obtenir les champs suivant :


id  différence
1   2                   (deux colonnes de différence)
2   2                   (deux colonnes de différence)
3   1                   (une colonne de différence)


J'ai bien identifié la commande


SELECT COUNT(*) FROM information_schema.COLUMNS WHERE table_name = 'matrice_test'


mais je n'ai pas réussi à introduire des conditions sur les valeurs des colonnes.
J'ai pensé faire un CROSSTABLE pour inverser lignes et colonnes mais le nombre d'enregistrements comme de champs est variable. Pareil pour lister les configurations possibles avec CASE. Il reste les opérateurs de comparaisons mais j'ai du mal à transposer la documentation à mon cas.
Si vous avez une piste, je suis preneur!


Bonne semaine à vous.

#9 Re : PL/pgSQL » Syntaxe/sous-requête WHERE dans un CROSSTAB » 07/06/2018 20:02:55

Je viens de découvrir l'utilisation des CTE (Common Table Expression) avec WITH (l'équivalent de votre syntaxe pour les requêtes imbriquées) qui rendent la construction de requêtes beaucoup plus aisées. Je vais persévérer encore un peu dans le postgreSQL...

https://www.postgresql.org/docs/9.1/sta … -with.html
http://www.portailsig.org/content/postg … recursives
http://www.craigkerstiens.com/2013/11/1 … not-using/

#10 Re : PL/pgSQL » Syntaxe/sous-requête WHERE dans un CROSSTAB » 07/06/2018 16:53:01

Effectivement j'avais repéré des syntaxes comme celle que vous proposez sur des forums pour passer outre les limites des fonctions AGGREGATE, mais ça ne permet par de l'insérer dans un SELECT comme :
SELECT AVG(SUM(ST_AREA(geom)) FROM ...
Ce qui est limitant lorsque l'on veut opérer des transformations de données sur des données déjà sélectionnées avec une procédure "complexe" (comme un CROSSTAB par exemple). Globalement je trouve que postgreSQL n'est pas pratique pour "produire de la donnée", c-a-d produire de nouvelles tables à partir de données transformées provenant d'autres tables. J'ai le sentiment que le SQL (et probablement le système relationnel) est plus conçu pour afficher et concaténer des données que pour les transformer, d’où l'approche atypique de Sotos dans sa procédure... Ou alors c'est que je ne suis pas suffisamment bon en SQL!

#11 Re : PL/pgSQL » Syntaxe/sous-requête WHERE dans un CROSSTAB » 06/06/2018 22:27:37

@ dverite : Par curiosité, je suis allé voir sur votre blog, et votre dernier post traite exactement de ce dont je veux parler! Merci beaucoup pour cette documentation sur les pivots dynamiques, c'est bien mieux que CROSSTAB!

#12 Re : PL/pgSQL » Syntaxe/sous-requête WHERE dans un CROSSTAB » 06/06/2018 21:57:47

Ah... Je n'avais pas bien compris la différence entre les deux versions de CROSSTAB. Effectivement j'ai des valeurs NULL, ce qui explique le message d'erreur. Merci beaucoup pour vos explications! Je veillerai par ailleurs à bien définir le type de mes colonnes, c'est plus sûr.


Par ailleurs, j'ai une question plus globale :
j'ai l'impression que postgresql ne semble pas fait pour traiter les données d'une base, mais plus pour l'organiser et les afficher suivant des critères.
En effet, il n'est pas possible de réaliser des chaînes de traitements statistiques complexes (comme AVG(SUM(ST_AREA()) -> aggregate function calls cannot be nested) et la constitution de tableaux croisés dynamiques (fonction CROSSTAB) nécessite d'expliciter les types des colonnes de sortie (donc pas pratique si la table d'entrée est amenée à s'incrémenter).


Globalement, à l'inverse de Sotos sur ce sujet (https://forums.postgresql.fr/viewtopic.php?id=4478) dans son avant dernier post, je me demande si il est pertinent d'utiliser postgreSQL pour réaliser des opérations de traitements statistiques sur des tables plutôt que d'utiliser une autre solution comme Rstat liée à une base postgreSQL (surtout pour un novice comme moi qui suis incapable d'écrire une procédure telle que celle de Sotos)?

#13 Re : PL/pgSQL » Syntaxe/sous-requête WHERE dans un CROSSTAB » 06/06/2018 15:45:23

Problème résolu!
Il fallait tout simplement supprimer les espaces (ce qui est bizarre car dans les requêtes sans CROSSTAB fonctionnent avec les espaces) comme suit (et aussi pour précision, parce que j'avais pas compris au début, il faut bien doubler les guillemets simple et non pas mettre des doubles guillemets) :


SELECT * FROM CROSSTAB(
'SELECT nomzone, annee, SUM(ST_AREA(geom) FROM parcellaire_total_test WHERE type=''abattis frais'' GROUP BY nomzone, annee ORDER BY 1,2',
'SELECT annee FROM parcellaire_total_test WHERE type=''abattis frais'' GROUP BY annee ORDER BY annee'
)
AS ct("nomzone" varchar, "2006" varchar, "2007" varchar, "2008" varchar, "2009" varchar, "2010" varchar, "2011" varchar, "2012" varchar, "2013" varchar, "2014" varchar, "2015" varchar, "2016" varchar)


Par contre je ne comprends toujours pas l'utilité de "doubler la requête" par :


'SELECT annee FROM parcellaire_total_test WHERE type=''abattis frais'' GROUP BY annee ORDER BY annee'


Si je l'enlève, j'obtiens une erreur de type :


ERROR:  return and sql tuple descriptions are incompatible
SQL state: 42601


Mais je ne vois pas à quoi cela correspond.

#14 Re : PL/pgSQL » Syntaxe/sous-requête WHERE dans un CROSSTAB » 06/06/2018 13:56:14

Bonjour,

Désolé si mon post n'était pas complet. Le message d'erreur renvoie une erreur de syntaxe :
ERROR:  syntax error at or near "abattis"
LINE 2: ...A(geom) FROM parcellaire_total_test WHERE type = 'abattis fr...
                                                                                          ^
SQL state: 42601
Character: 109

J'avais déjà testé les doubles guillemets, qui renvoient l'erreur suivante (mais j'utilise la clause WHERE dans un SELECT avec des simples guillemets, donc j'imagine que ça doit être la même chose ici).

ERROR:  column "abattis frais" does not exist
LINE 1: ...CT annee FROM parcellaire_total_test WHERE type = "abattis f...
                                                             ^
QUERY:  SELECT annee FROM parcellaire_total_test WHERE type = "abattis frais" GROUP BY annee ORDER BY annee
SQL state: 42703

#15 PL/pgSQL » Syntaxe/sous-requête WHERE dans un CROSSTAB » 05/06/2018 23:30:42

robinson
Réponses : 9

Bonjour,

Je fais appel une nouvelle fois à vos lumières pour résoudre le problème suivant.
J'ai écrit ce code pour réaliser un CROSSTAB sur une table décrivant des polygones portant les informations (nomzone, annee, geom, type), afin de réaliser des calculs de surface de polygones en fonction des annees et des zones.

SELECT * FROM CROSSTAB(
'SELECT nomzone, annee, SUM(ST_AREA(geom) FROM parcellaire_total_test GROUP BY nomzone, annee ORDER BY 1,2',
'SELECT annee FROM parcellaire_total_test WHERE type = 'abattis frais' GROUP BY annee ORDER BY annee'
)
AS ct("nomzone" varchar, "2006" varchar, "2007" varchar, "2008" varchar, "2009" varchar, "2010" varchar, "2011" varchar, "2012" varchar, "2013" varchar, "2014" varchar, "2015" varchar, "2016" varchar)

Ce code est fonctionnel (à priori, je n'ai pas vérifié la cohérence des données).
Néanmoins, je souhaite rajouter une clause WHERE afin de séléctionner les données de sortie en fonction du type. J'ai donc écrit :

SELECT * FROM CROSSTAB(
'SELECT nomzone, annee, SUM(ST_AREA(geom) FROM parcellaire_total_test WHERE type = 'abattis frais'' GROUP BY nomzone, annee ORDER BY 1,2',
'SELECT annee FROM parcellaire_total_test WHERE type = 'abattis frais' GROUP BY annee ORDER BY annee'
)
AS ct("nomzone" varchar, "2006" varchar, "2007" varchar, "2008" varchar, "2009" varchar, "2010" varchar, "2011" varchar, "2012" varchar, "2013" varchar, "2014" varchar, "2015" varchar, "2016" varchar)

Mais après plusieurs essais de placement de la clause WHERE, aucune disposition ne marche. L'utilisation de WHERE est-elle possible? Y a t'il une autre fonction afin d'arriver à mon résultat? Et dernière questions pouvez vous m'expliquer la fonction du deuxième 'SELECT'? Je n'ai pas bien compris pourquoi elle était nécessaire (j'ai bêtement recopié des scripts sur des forums).

Merci d'avance!

#16 Re : PL/pgSQL » INSERT INTO à partir d'un SELECT » 15/05/2018 20:36:04

Bonjour,

Je suis effectivement arrivé à la même conclusion que vous et j'ai utilisé UPDATE pour l'insertion des données dans les enregistrements existants.
J'ai juste eu un problème avec votre formulation directe qui n'a pas fonctionné (sans que je sache très bien pourquoi), aussi j'ai utilisé un AS avec une table temporaire :
UPDATE  departements  SET nomregions = regions_temp.nomregions
FROM (
SELECT regions.nomregions AS nomregions
FROM regions
JOIN departements
ON ST_CONTAINS(regions.geom, departements.geom)
)
AS regions_temp;

Merci pour votre contribution!

#17 Re : PL/pgSQL » INSERT INTO à partir d'un SELECT » 14/05/2018 16:43:45

Merci pour votre prompte réponse. Je comprends mieux pourquoi la commande ne marche pas, mais dans ce cas comment insérer une colonne dans une table à partir d'une jointure sur cette propre table?
J'ai fait des essais et il est possible de faire un CREATE TABLE satisfaisant avec le SELECT tel qu'il est écrit, c'est à dire créer une copie de la table 'departements' avec les résultats de la jointure et des données de base, mais comment éditer une table existante? C'est un peu fastidieux de devoir recréer une table à chaque fois puis de supprimer l'ancienne... Ce problème se pose d'ailleurs pour associer des clés primaires et étrangères sans passer par de la saisie manuelle.
Cordialement

#18 PL/pgSQL » INSERT INTO à partir d'un SELECT » 14/05/2018 15:56:25

robinson
Réponses : 4

Bonjour,

Dans le cadre d'une migration d'une base de données géographique depuis un SIG (shapefiles) vers PostgreSQL, je dois créer l'architecture relationnelle de la base à partir des données existantes.
A partir de deux tables existantes représentant deux niveaux de découpage de zones géographiques (par exemple les 'departements' et les 'regions', comprenant les colonnes 'nomdept'/'nomregion' - clé primaires, et leur 'geometrie'), je souhaite intégrer sur la table 'departements' la colonne 'nomregion' avec une contrainte de clé étrangère se référant à la clé primaire 'nomregion de la table 'regions'. Bien sûr, je souhaite aussi que le 'nomdept' corresponde au 'nomregion' qui contient sa 'geometrie'.
J'ai d'abord créé la colonne 'nomregion' dans la table 'departements' (je n'ai pas trouvé de solution pour que la requête renvoie directement la création d'une nouvelle colonne) :

ALTER TABLE departements ADD COLUMN nomregion VARCHAR
CONSTRAINT nomregion
REFERENCES regions (nomregion);

Puis :

INSERT INTO departements (nomregion)
SELECT regions.nomregions
FROM regions
JOIN departements
ON ST_CONTAINS(regions.geom, departements.geom)

Mais j'obtiens une erreur
"null value in column "nomdept" violates not-null constraint
DETAIL:  Failing row contains (null, null, exemplenomdept)."

Sauf que :
- La commande select seule renvoie bien les données voulues
- je ne comprends pas d’où sortent les valeurs NULL sachant que j'ai bien spécifié que l'INSERT ne portait que sur la colonne 'nomregion'

J'ai bien essayé un ON CONFLICT DO UPDATE ou DO NOTHING mais ces commandes ne sont pas reconnues (bizarre...).

Vous avez une idée d'où pourrait venir l'erreur? Ou d'une meilleure formulation / fonction à employer (j'ai testé avec UPDATE mais ça ne marche pas trop avec les jointures spatiales j'ai l'impression).

Merci d'avance!

#19 Re : PL/pgSQL » Insérer des enregistrements incrémentés avec une séquence dans table » 11/05/2018 17:23:59

Bonjour,

Cette fonction est magique! Moi qui pensait qu'il fallait passer par un montage complexe avec une séquence et une sorte de boucle... On découvre toujours de nouvelles fonctions!
Merci beaucoup.

#20 PL/pgSQL » Insérer des enregistrements incrémentés avec une séquence dans table » 07/05/2018 20:41:00

robinson
Réponses : 2

Bonjour,

Après moultes recherches non concluantes sur le net, je me demandais si il était possible d’insérer 'automatiquement' des enregistrements incrémentés dans une table suivant une séquence spécifique. Je précise que je ne veux insérer que le champ incrémenté sur un pas défini.
Pour être plus précis, je cherche à remplir une table année ne possédant que le champ annee de 2005 à 2020 par exemple.
J'ai bien le

CREATE SEQUENCE annees INCREMENT BY 1
MINVALUE 2000
NO MAXVALUE
START WITH 2005
CACHE 100
OWNED BY année.annee

Suivi d'un

INSERT INTO année (annee) VALUES (nextval('annees'))

Mais cette dernière instruction ne vaut que pour un enregistrement à la fois.

J'aimerai arriver à quelque chose du genre
INSERT INTO annee (annee) VALUES (nextval('annees'), min_value('2005'), max_value('2020'))

Sauf que min_value et max_value ne sont pas des arguments de la fonction INSERT VALUES

Une idée?

#21 Re : Installation » Erreur (0x0000274D/10061) » 13/04/2018 16:59:49

Bonjour,

Je suis allé voir du côté de d'EXPOSE et c'était une bonne piste. Il y a effectivement là des commandes qui permettent de lister/d'assigner des ports au lancement d'un docker
https://stackoverflow.com/questions/221 … -in-docker
https://forums.docker.com/t/how-to-expo … ner/3252/5

Du coup j'ai fait un :
docker stop container
Puis un :
docker run -d -p port
Pour relancer le container avec le bon port. Et ça a marché.
Merci beaucoup pour les conseils, je pense que seul j'y aurai passé quelques jours de plus...
@dverite : le port indiqué par le netstat taupen. Mais effectivement c'est bien le port du DNS, j'ai confondu avec ceux du ps -a, qui n'étaient pas affichés.
Mais le service postgres était bien lancé, le docker ps était formel (et j'ai vérifié dans les logs, aucun problème). C'était donc bien un problème de routage.

Encore merci!

#22 Re : Installation » Erreur (0x0000274D/10061) » 12/04/2018 15:05:28

Bonjour,

Après une analyse des ports plus approfondie (en jouant avec 'docker ps -a' pour voir les ports des containers, 'netstat -t -a -u -p -e -n) pour voir les connections réseaux et 'nmap -p numéroport adresseip' pour vérifier l'ouverture des port, il apparait que :
- Aucune adresse ip n'est affectée au docker postgis avec docker ps (mais j'imagine que du coup il doit prendre des paramètres par défaut ou quelque chose dans ce goût là).
- Le port 53 est bien ouvert pour l'adresse locale visée.

Donc je me retrouve bien dans un problème d'assignation de port non compatible avec postgresql. Quelqu'un saurait comment on fait pour affecter un port supérieur à 1024?

#23 Re : Installation » Erreur (0x0000274D/10061) » 11/04/2018 19:19:38

Effectivement ça marche mieux en précisant /0 (j'imagine que c'est pour accepter tout type de masques CIDR). Mais bon comme je le pressentais dans mon post précédent, un nmap m'a bien renseigné que mon port était fermé, et j'essaie désormais de le paramétrer avec iptable. Donc j'imagine que ça n'a plus grand chose à voir avec postgresql...
Merci pour votre aide!

#24 Re : Installation » Erreur (0x0000274D/10061) » 11/04/2018 16:41:58

Tout d'abord merci pour vos réponses, c'est fort sympathique.
@rjuju Effectivement cette distribution permet d'être routeur internet en plus d'y stocker une base de donnée. Néanmoins je déconnecte le cable ethernet quant je veux travailler dessus, au cas ou ça détourne l'architecture (c'est un peu stupide mais je commence à devenir parano).
Concernant les lignes de commande :
- postgres est bien démarré sur le serveur, de toute façon le docker est bien construit et je le relance régulièrement. La commande sudo ps aux |grep postgre renvoie :
pirate 1489 0.0 0.2 4192 1784 tty1 S+ 13:49 0:00 grep postgre
- Par contre, il n'y a visiblement aucun port 5432... Le port indiqué est 53, ce qui ne me convient pas car postgresql (pgadmin) n'accepte que les ports au dessus de 1024...
- Du coup j'ai bien essayé de reconfigurer les ports avec iptable, mais le pare-feu n'est pas installé et il m'est impossible d'installer le package pour l'instant (E: unable to locate package). J'ai essayé plusieurs techniques mais j'ai l'impression que le package n'est pas compatible avec hypriot OS.

@ruizsebastien
J'ai essayé la configuration proposée mais visiblement la syntaxe n'est pas bonne, postgresql ne se lançant pas. Apparement il ne reconnait pas les adresses 0.0.0.0
Mais ça m'a quand même mis sur une piste, et après avoir lu (https://www.postgresql.org/docs/9.1/sta … -conf.html) j'ai essayé :
host    all             all             172.24.1.102/32         md5
host    all                all                172.24.1.1/32            md5
sans succès, mais du coup je pense que c'est à cause du port comme indiqué plus tôt.

Merci pour vos réponses,  je continue à chercher sur la piste du port et je vous tiens au courant.

#25 Installation » Erreur (0x0000274D/10061) » 10/04/2018 23:15:36

robinson
Réponses : 9

Bonjour,

Je poste en désespoir de cause à propos de la fameuse erreur de routage (0x0000274D/10061) qui arrive à beaucoup de monde apparemment :

"Unable to connect to server:

could not connect to server: Connection refused (0x0000274D/10061)
Is the server running on host "172.24.1.1" and accepting
TCP/IP connections on port 5432?"

Je souhaite me connecter via wifi depuis mon pc sous windows 7 avec pg admin (ou qgis, mais c'est pareil) à un serveur postgresql installé sur un raspberry (avec l'excellente distribution raspbian docker pour une application de serveur embarqué webSIG, j'ai nommé géopoppy : https://github.com/jancelin/geo-poppy/wiki). Je précise à ce niveau que même si j'ai une certaine culture numérique je ne suis pas administrateur réseau et que je ne comprend pas bien l'architecture de tous les ports et adresses trouvées sur les deux terminaux avec netstat et ipconfig.
J'ai déjà réussi à me connecter au serveur la première fois (ou j'ai d'ailleurs créé ma base). Le lendemain, après redémarrage, cette erreur est apparue. Je n'ai eu aucune erreur lors de l'installation de postgresql et j'arrive très bien à profiter de la fonction routeur internet du raspberry (même après l'apparition du message d'erreur).
J'ai parcouru une multitude de posts la concernant, et essayé le plupart des techniques recommandées :
- J'ai essayé plusieurs fois de tout réinstaller : le serveur et postgresql (j'ai bien supprimé le répertoire data et les clés registre), mais l'erreur finissait par réapparaitre.
- J'ai essayé une multitude de configurations pour les fichiers pg_hba.conf et posgresql.conf
- J'ai bien sûr relancé le service postgresql à chaque essai.
- J'ai paramétré mon pare-feu ouvert dans les deux sens pour le port 5432, et autorisé le programme postgres pour toutes les connexions.
- J'ai même essayé la technique de l'optimisation de l'allocation de la RAM dans le fichier posgresql.conf

J'ai bien lu ce post : https://forums.postgresql.fr/viewtopic.php?id=4665 mais je n'ai pas compris toutes les commandes. Je les ai testées mais certaines n'étaient pas reconnues.
Je suis à court d'idée et ça fait déjà quatre jours complets que je suis dessus...

Les paramètres de mon pc :
Carte réseau sans fil Connexion réseau sans fil 2 :
   Suffixe DNS propre à la connexion. . . :
   Adresse IPv6 de liaison locale. . . . .: fe80::c441:7bc3:635:101c%20
   Adresse IPv4. . . . . . . . . . . . . .: 172.24.1.102
   Masque de sous-réseau. . . . . . . . . : 255.255.255.0
   Passerelle par défaut. . . . . . . . . : 172.24.1.1

Les paramètres du serveur raspberry :
wlan0
inet addr:172.24.1.1

Voici les dernières versions de mes fichiers :
pg_hba.conf :

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5
host    all                all                172.24.1.102/32            md5

postgresql.conf :
# - Connection Settings -

listen_addresses = '*'        # what IP address(es) to listen on;
                    # comma-separated list of addresses;
                    # defaults to 'localhost'; use '*' for all
                    # (change requires restart)
port = 5432                # (change requires restart)


Merci d'avance si vous avez une piste!

Cordialement.

Pied de page des forums

Propulsé par FluxBB