Requêtes POSTGIS
Les départements qui intersecte la Garonne :
Les forêts autour des forêts de conifères :
WITH req_f_conifere as (SELECT fid,geom FROM occsol.clc12 WHERE code_12='312') --forêts de conifères
--pour chaque forêt de conifère, je veux la liste des types de forêts
-- combien de forêts voisines des forêts de conifères ?
SELECT req_f_conifere.fid,req_f_conifere.geom, count(*) as nbre_forets,
string_agg(distinct code_12,', ') as liste_type_forets
-- clc12.code_12,clc12.area_ha
FROM occsol.clc12
JOIN req_f_conifere
ON st_touches(clc12.geom, req_f_conifere.geom)
WHERE code_12 in ('313','311','324')--les autres forêts
GROUP BY req_f_conifere.fid,req_f_conifere.geom
ORDER BY 1;
les parcelles bâties :
--les parcelles bâties
CREATE MATERIALIZED VIEW toulouse.vm_parcelles_batis_overlaps_1 AS
SELECT DISTINCT p.fid, p.geom, p.id, p.numero
FROM toulouse.parcelles as p
JOIN toulouse.batiments as b
ON st_overlaps(p.geom,b.geom)--batis qui chevauchent parcelles
UNION
SELECT DISTINCT p.fid, p.geom, p.id, p.numero
FROM toulouse.parcelles as p
JOIN toulouse.batiments as b
ON st_contains(p.geom,b.geom)--parcelles qui contiennent batis
--parcelles qui contiennent un point situé à l'interieur des batis
CREATE VIEW toulouse.v_parcelle_centroide_bati as
SELECT DISTINCT p.fid, p.geon, p.id, p.numero,
FROM toulouse.parcelles as p,
JOIN toulouse.batiment as b
ON st_contain(p.geom,st_pointomsurface(b.geom)))
--geometrie invalide
SELECT fid, geom,(st_isvaliddetail(geom)).location
FROM toulouse.batiments
WHERE not st_isvalid(geom);
--les parcelles qui se chevauchent
SELECT distinct p1.*
FROM toulouse.parcelles as p1
JOIN toulouse.parcelles as p2
ON st_overlaps(p1.geom,p2.geom)
WHERE p1.fid!=p2.fid
-- les batis a 500m du zenith (fid=131389)
with req_zenith as (SELECT fid, geom
FROM toulouse.batiments
WHERE fid=131389)
SELECT b.*
FROM req_zenith
JOIN toulouse.batiments as b
ON st_dwithin(req_zenith.geom,b.geom,500)
WHERE b.fid != req_zenith.fid ;
--zone 200m autour de la Garonne
SELECT row_number() over() as fid,
st_buffer(geom, 200) as geom_200m
FROM hydro.v_garonne;
--modification de la vue v_garonne
CREATE OR REPLACE VIEW hydro.v_garonne
AS
SELECT fid,
geom,
topooh,
st_length(geom) AS longueur
FROM hydro.cours_o
WHERE fid in(130658,33421);
--découper les parcelles du quartier 828
--par le buffer de 200m
SELECT parcelles.fid,
st_intersection(parcelles.geom, st_buffer(v_garonne.geom,200)) as geom_inter,
parcelles.id
FROM toulouse.parcelles
JOIN hydro.v_garonne
ON st_dwithin(parcelles.geom,v_garonne.geom,200)
WHERE parcelles.id ilike '%828%'
Compléments POSTGIS
Deux possibilités pour croiser les cours d'eau avec les départements :
SELECT departements.*
FROM hydro.cours_o
JOIN admin.departements
ON st_intersects(cours_o.geom, departements.geom)
WHERE st_length(cours_o.geom)=(select max(st_length(geom))
from hydro.cours_o );
--autre solution
CREATE VIEW admin.v_dep_cours_o_fid0 AS
WITH req_cours_o_long as (
SELECT geom
FROM hydro.cours_o
ORDER BY st_length(geom) DESC LIMIT 3)
SELECT row_number() over() fid0, departements.*
FROM req_cours_o_long
JOIN admin.departements
ON st_intersects(req_cours_o_long.geom, departements.geom)
ORDER BY 1
row_number() over() fid0
permet de définir un identifiant unique pour afficher tous les objets (même ceux identiques) dans QGIS en passant par le gestionnaire de base de données.
Quand vous avez des doublons dans les identifiants, vous pouvez passer par la connexion postgis (dans le gestionnaire de sources de données et décocher "vérifier l'unicité de la clé primaire")
La vue avec le nom des cours d'eau qui traversent les départements :
```CREATE VIEW admin.v_dep_cours_o_fid0 AS
WITH req_cours_o_long as (
SELECT geom, topooh
FROM hydro.cours_o
ORDER BY st_length(geom) DESC LIMIT 3)
SELECT row_number() over() fid0, departements.*, topooh
FROM req_cours_o_long
JOIN admin.departements
ON st_intersects(req_cours_o_long.geom, departements.geom)
ORDER BY 1
row_number() over(**order by fid**) fid0 permet de trier par la colonne fid avant de mettre les numéros de ligne
Pour n'avoir qu'un seul objet et la liste des cours d'eau, on fait des groupes par département :
```sql_more=
WITH req_cours_o_long as (
SELECT geom, topooh
FROM hydro.cours_o
ORDER BY st_length(geom) DESC LIMIT 3)
SELECT departements.fid, code_insee, nom, departements.geom,
string_agg(topooh, ', ') as cours_eau
FROM req_cours_o_long
JOIN admin.departements
ON st_intersects(req_cours_o_long.geom, departements.geom)
GROUP BY 1,2,3,4
ORDER BY 1;
Créer une table à partir d'une fonction spatiale :
```sql_more= --création de l'objet region occitanie CREATE TABLE admin.region( code_reg text primary key, nom text, geom geometry(multipolygon,2154) ); INSERT INTO admin.region SELECT '76' as code_reg, 'Occitanie' as nom, st_union(geom ) as geom FROM admin.communes;
### Sélectionner des objets qui ne correspondent pas à un critère spatial
Par exemple :
```sql_more=
--y a t il des communes qui n'ont pas
--de cours d'eau (le nom du cours d'eau doit être renseigné)
1ere étape : ne travailler que sur les cours d'eau d'Occitanie en créant une vue matérialisée qui fige le résultat de la requête dans une table
```sql_more=
CREATE MATERIALIZED VIEW hydro.vm_cours_o_occitanie AS
SELECT cours_o.fid, topooh, cours_o.geom
FROM hydro.cours_o
JOIN admin.region
ON st_intersects(region.geom,cours_o.geom);
2eme étape : selection des communes qui ont des cours d'eau :
```sql_more=
SELECT communes.fid
FROM hydro.vm_cours_o_occitanie
JOIN admin.communes
ON st_intersects(vm_cours_o_occitanie.geom,communes.geom)
WHERE topooh is not null
SELECT *
FROM admin.communes
WHERE fid not in (
SELECT communes.fid
FROM hydro.vm_cours_o_occitanie
JOIN admin.communes
ON st_intersects(vm_cours_o_occitanie.geom,communes.geom)
WHERE topooh is not null );
Requête spatiale sur l'occupation du sol d'une commune
```sql_more= --L'occupation du sol -- pour la commune de Villefranche d'Astarac(32465) SELECT ocs_ge32.fid,code_cs,code_us, st_intersection(ocs_ge32.geom,communes.geom) geom FROM admin.communes JOIN occsol.ocs_ge32 ON st_intersects(ocs_ge32.geom,communes.geom) WHERE insee_com='32465' -- ou nom ilike 'villefranche%astarac%'
Mais il faut etre sûr que les résultat de l'intersection ne ramene que des multipolygones :
```sql_more=
--L'occupation du sol
-- pour la commune de Villefranche d'Astarac(32465)
CREATE VIEW occsol.v_ocs_villefranche_astarac AS
SELECT ocs_ge32.fid,code_cs,code_us,
st_multi(--définis en multipolygones
ST_CollectionExtract(--que des polygones ou des multipolygones
st_intersection(ocs_ge32.geom,communes.geom)--intersection
,3)-- 3 pour sélectionner que les polygones
) as geom_inter
FROM admin.communes
JOIN occsol.ocs_ge32
ON st_intersects(ocs_ge32.geom,communes.geom)
WHERE insee_com='32465'; -- ou nom ilike 'villefranche%astarac%'
```sql_more=
--L'occupation du sol
-- pour la commune de Villefranche d'Astarac(32465)
-- et les communes autour
CREATE OR REPLACE VIEW occsol.v_ocs_villefranche_astarac as
WITH req_communes as (SELECT st_union(autres_communes.geom) --pour n'avoir qu'un polygone commune à croiser avec l'occupation du sol
FROM admin.communes as commune_villefranche
JOIN admin.communes as autres_communes
ON st_intersects(commune_villefranche.geom,autres_communes.geom)
WHERE commune_villefranche.insee_com='32465')
SELECT ocs_ge32.fid,code_cs,code_us,
st_multi(--définis en multipolygones
ST_CollectionExtract(--que des polygones ou des multipolygones
st_intersection(ocs_ge32.geom,communes.geom)--intersection
,3)-- 3 pour sélectionner que les polygones
)::geometry(multipolygon,2154) as geom_inter
FROM req_communes as communes
JOIN occsol.ocs_ge32
ON st_intersects(ocs_ge32.geom,communes.geom) ;
## Exercice : mettre en place une base de données sur les panneaux publicitaires
Données :
**Panneaux publicitaires** :
Localisation
Il y a plusieurs **types de panneaux** à gérer :
* les panneaux sucettes traditionnels : ce sont des planimètres rectangulaires installés sur des supports verticaux ;
* les panneaux sucettes numériques : ils comprennent des écrans lumineux qui permettent d’afficher un contenu dynamique comme des vidéos ;
* les panneaux sucettes interactifs : ils sont dotés d’écrans tactiles qui offrent la possibilité aux clients d’interagir avec les contenus ;
* les panneaux sucettes rotatifs : montés sur un mécanisme spécial, ils tournent lentement sur eux-mêmes pour capter l’attention du client.
Les emplacements sont loués par des **publicitaires** pour une période donnée mais peuvent être utilisés par la **mairie** (convention avec le publicitaire)
Les panneaux sont soit muraux soit scellés au sol (**format**)
SCRIPT SQL issu du MCD/MLD :
```sql_more=
CREATE EXTENSION postgis;
CREATE SCHEMA publicite;
CREATE SCHEMA admin;
CREATE TABLE publicite.type_panneaux(
id_type_panneaux INT GENERATED ALWAYS AS IDENTITY,
nom TEXT,
PRIMARY KEY(id_type_panneaux)
);
CREATE TABLE publicite.publicitaire(
id_publicitaire INT GENERATED ALWAYS AS IDENTITY,
nom TEXT,
PRIMARY KEY(id_publicitaire)
);
CREATE TABLE admin.commune(
cog VARCHAR(5) ,
nom_com TEXT,
geom geometry(multipolygon,2154),
PRIMARY KEY(cog)
);
CREATE TABLE publicite.format(
id_format INT GENERATED ALWAYS AS IDENTITY,
libelle TEXT,
PRIMARY KEY(id_format)
);
CREATE TABLE publicite.panneaux(
id_panneaux INT GENERATED ALWAYS AS IDENTITY,
geom geometry(point,2154),
id_format INTEGER NOT NULL,
id_type_panneaux INTEGER NOT NULL,
PRIMARY KEY(id_panneaux),
FOREIGN KEY(id_format) REFERENCES publicite.format(id_format),
FOREIGN KEY(id_type_panneaux) REFERENCES publicite.type_panneaux(id_type_panneaux)
);
CREATE TABLE publicite.louer(
id_panneaux INTEGER,
id_publicitaire INTEGER,
date_debut_location DATE,
duree INTEGER,
PRIMARY KEY(id_panneaux, id_publicitaire),
FOREIGN KEY(id_panneaux) REFERENCES publicite.panneaux(id_panneaux),
FOREIGN KEY(id_publicitaire) REFERENCES publicite.publicitaire(id_publicitaire)
);
CREATE TABLE publicite.convention(
id_publicitaire INTEGER,
cog VARCHAR(5) ,
date_convention DATE,
PRIMARY KEY(id_publicitaire, cog),
FOREIGN KEY(id_publicitaire) REFERENCES publicite.publicitaire(id_publicitaire),
FOREIGN KEY(cog) REFERENCES admin.commune(cog)
);
Inserer les données dans les tables de référence :
sql_more=
INSERT INTO publicite.format(libelle)
VALUES ('muraux' ),('scellés au sol' );
INSERT INTO publicite.type_panneaux(nom)
VALUES('panneaux sucettes traditionnels'),
('panneaux sucettes numériques'),
('panneaux sucettes interactifs'),
('panneaux sucettes rotatifs');
sql_more=
DROP VIEW occsol.v_ocs_villefranche_astarac;### Faire la connexion avec QGIS
## Ajout du libellé d'occupation du sol à la vue sur Villefranche d'Astarac
Après avoir importer la nomenclature dans la base de données (avec QGIS et le gestionnaire de base de données), on modifie la vue avec le libellé issu de la nomenclature
```sql_more=
WITH req_communes AS (
SELECT st_union(autres_communes.geom) AS geom
FROM admin.communes commune_villefranche
JOIN admin.communes autres_communes ON st_intersects(commune_villefranche.geom, autres_communes.geom)
WHERE commune_villefranche.insee_com::text = '32465'::text
)
SELECT ocs_ge32.fid,
ocs_ge32.code_cs,n_cs.libelle,
ocs_ge32.code_us,n_us.libelle,
st_multi(st_collectionextract(st_intersection(ocs_ge32.geom, communes.geom), 3))::geometry(MultiPolygon,2154) AS geom_inter
FROM req_communes communes
JOIN occsol.ocs_ge32 ON st_intersects(ocs_ge32.geom, communes.geom)
JOIN occsol.nomenclature_ocsge n_cs
ON n_cs.code=ocs_ge32.code_cs
JOIN occsol.nomenclature_ocsge n_us
ON n_us.code=ocs_ge32.code_us
;
CREATE OR REPLACE VIEW occsol.v_ocs_villefranche_astarac AS WITH req_communes AS ( SELECT st_union(autres_communes.geom) AS geom FROM admin.communes commune_villefranche JOIN admin.communes autres_communes ON st_intersects(commune_villefranche.geom, autres_communes.geom) WHERE commune_villefranche.insee_com::text = '32465'::text ) SELECT ocs_ge32.fid, ocs_ge32.code_cs,n_cs.libelle as libelle_couverture, ocs_ge32.code_us,n_us.libelle as libelle_usage, st_multi(st_collectionextract(st_intersection(ocs_ge32.geom, communes.geom), 3))::geometry(MultiPolygon,2154) AS geom_inter FROM req_communes communes JOIN occsol.ocs_ge32 ON st_intersects(ocs_ge32.geom, communes.geom) JOIN occsol.nomenclature_ocsge n_cs ON n_cs.code=ocs_ge32.code_cs JOIN occsol.nomenclature_ocsge n_us ON n_us.code=ocs_ge32.code_us ;
## Croisement de l'occupation du sol avec l'emprise de 20m des routes
L'objectif est d'extraire l'emprise des routes de l'occupation du sol
### 1ere étape : créer un buffer de 20m autour du réseau routier
```sql_more=
SELECT
st_union(st_buffer(geom_inter, 20))::geometry(multipolygon,2154) as geom20m
FROM occsol.v_ocs_villefranche_astarac
WHERE code_us='US4.1.1';
sql_more=
WITH
req_zone20m /*zone 20m autour des routes */ AS
(SELECT st_union(
st_buffer(geom_inter, 20)
)::geometry(multipolygon,2154)
as geom20m
FROM occsol.v_ocs_villefranche_astarac
WHERE code_us='US4.1.1' --le reseau routier
),
req_zone5m /*zone 5m autour des cours d'eau */ AS
(SELECT st_union(st_buffer(cours_o.geom,5))::geometry(multipolygon,2154) geom5m
FROM hydro.cours_o
JOIN req_zone20m
ON (st_intersects(req_zone20m.geom20m, cours_o.geom))
)
--résultat du croisement entre les 2 buffers avec st_difference()
SELECT st_difference(geom20m,geom5m) as geom20moins5
FROM req_zone20m JOIN req_zone5m
ON st_intersects(geom20m,geom5m)
sql_more=
SELECT st_buffer(st_buffer(st_union(geom_inter),20),-19) as geom
FROM occsol.v_ocs_villefranche_astarac
WHERE code_us in('US1.3', 'US2', 'US235', 'US3','US4.1.2',
'US4.1.3','US4.1.4','US4.1.5','US4.2','US4.3','US5',
'US6.1')
OR code_cs in ('CS1.1.1.1','CS1.1.2.1','CS1.1.2.2')
### Ajout des autres usages du sol faisant barrière à la continuité écologique
```sql_more=
--à regrouper avec le buffer des routes : US1.3, US2, US235, US3,
--US4.1.2, US4.1.3,US4.1.4,US4.1.5,US4.2,US4.3,US5,
--US6.1
SELECT st_union(geom_inter) as geom
FROM occsol.v_ocs_villefranche_astarac
WHERE code_us in('US1.3', 'US2', 'US235', 'US3','US4.1.2',
'US4.1.3','US4.1.4','US4.1.5','US4.2','US4.3','US5','US6.1')
OR code_cs in ('CS1.1.1.1','CS1.1.2.1','CS1.1.2.2')
On rassemble le buffer des routes avec les autres zones artificialisées :
```sql_more=
WITH
req_zone20m AS (
SELECT st_union(
st_buffer(geom_inter, 20)
)::geometry(multipolygon,2154)
as geom20m
FROM occsol.v_ocs_villefranche_astarac
WHERE code_us='US4.1.1' --le reseau routier
),
req_autres_zones as (
SELECT st_buffer(st_buffer(st_union(geom_inter),20),-19) as geom_autre_20m
FROM occsol.v_ocs_villefranche_astarac
WHERE code_us in('US1.3', 'US2', 'US235', 'US3','US4.1.2',
'US4.1.3','US4.1.4','US4.1.5','US4.2','US4.3','US5',
'US6.1')
OR code_cs in ('CS1.1.1.1','CS1.1.2.1','CS1.1.2.2')
),
req_union_des_2_couches as (SELECT geom20m
FROM req_zone20m
union
SELECT geom_autre_20m
FROM req_autres_zones)
SELECT st_union(geom20m) as geom20m_total
FROM req_union_des_2_couches;
La requête complète avec création de la vue :
```sql_more= CREATE MATERIALIZED VIEW occsol.vm_inverse_trame_verte AS WITH req_zone20m AS ( SELECT st_union( st_buffer(geom_inter, 20) ) as geom20m FROM occsol.v_ocs_villefranche_astarac WHERE code_us='US4.1.1' --le reseau routier ), req_autres_zones as ( SELECT st_buffer(st_buffer(st_union(geom_inter),20),-19) as geom_autre_20m FROM occsol.v_ocs_villefranche_astarac WHERE code_us in('US1.3', 'US2', 'US235', 'US3','US4.1.2', 'US4.1.3','US4.1.4','US4.1.5','US4.2','US4.3','US5', 'US6.1') OR code_cs in ('CS1.1.1.1','CS1.1.2.1','CS1.1.2.2') ), req_union_des_2_couches as (SELECT geom20m FROM req_zone20m union SELECT geom_autre_20m FROM req_autres_zones) , req_zones_artificialisees as (SELECT st_union(geom20m) as geom20m_total FROM req_union_des_2_couches)
, req_zone5m as (SELECT st_union(st_buffer(cours_o.geom,5))::geometry(multipolygon,2154) geom5m FROM hydro.cours_o JOIN req_zones_artificialisees ON (st_intersects(req_zones_artificialisees.geom20m_total, cours_o.geom)) ) SELECT 1 as fid, st_difference(geom20m_total,geom5m)::geometry(multipolygon,2154) as geom20moins5 FROM req_zones_artificialisees JOIN req_zone5m ON st_intersects(geom20m_total,geom5m);
### Création des trames vertes :
```sql_more=
CREATE VIEW occsol.v_trame_verte AS
WITH req_union_communes as (
SELECT st_union(autres_communes.geom) AS geom
FROM admin.communes commune_villefranche
JOIN admin.communes autres_communes
ON st_intersects(commune_villefranche.geom, autres_communes.geom)
WHERE commune_villefranche.insee_com::text = '32465'
)
SELECT 1 as fid,st_difference(geom,geom20moins5)::geometry(multipolygon,2154) as geom
FROM req_union_communes
JOIN occsol.vm_inverse_trame_verte ON st_intersects(geom,geom20moins5);
sql_more=
WITH req as (SELECT (st_dump(geom)).path[1] as fid,(st_dump(geom)).geom
FROM occsol.v_trame_verte)
SELECT *
FROM req
WHERE st_area(geom)>10000;