Prostorové dotazy - druhá část
Otázky
odkaz
12. Vyberte katastrální území, ve kterých leží alespoň částečně jedna vodní plocha, seskupte tyto území podle kódu NUTS LAU1. Uveďte jaký kód NUTS má největší výměru a z kolika katastrálních území se skládá? |
(GPKG: 75s vs PostGIS: 0.3s) CZ0313, 78 |
7. Kolik železničních stanic leží v lese a zároveň jejich název nezačíná na písmeno 'L'? |
100 |
2. Kolika obcemi v ČR neprochází žádná silnice? |
241 |
4. Vyberte silnice, které kříží vodní toky. Jaké procento z těchto silnic tvoří silnice první třídy? |
14,5% |
5. Kolik procent rybníků z celkového počtu leží celou svojí plochou na území Jihočeského kraje? |
41,85% |
10. Kolik vodních ploch leží alespoň částí své plochy ve vzdálenosti do 10 km od poledníku se zeměpisnou délkou 15°? |
45 |
3. Kolik obcí leží na hranici ČR? |
285 |
11. Kolik obcí se dotýká alespoň jedním liniovým segmentem hranice kraje? |
1248 |
Řešení
12. Vyberte katastrální území, ve kterých leží alespoň částečně jedna vodní plocha, seskupte tyto území podle kódu NUTS LAU1. Uveďte jaký kód NUTS má největší výměru a z kolika katastrálních území se skládá? |
(GPKG: 75s vs PostGIS: 0.3s) CZ0313, 78 |
SELECT kod_lau1, count(*) AS pocet
FROM ac.katastralniuzemipolygony AS k
WHERE objectid IN
(
SELECT DISTINCT k.objectid
FROM ac.katastralniuzemipolygony AS k
JOIN ar.vodniplochy AS v
ON st_intersects(k.geom, v.geom)
)
GROUP BY kod_lau1
ORDER BY pocet DESC
LIMIT 1;
7. Kolik železničních stanic leží v lese a zároveň jejich název nezačíná na písmeno 'L'? |
100 |
SELECT count(*)
FROM ar.zeleznicnistanice as z
join ar.lesy as l
ON st_intersects(z.geom, l.geom)
where nazev not like 'L%';
výsledek vychází jinak v porovnání s Esri ArcGIS, mnoho stanic leží na hranici lesa
WITH lesy1 AS
(
SELECT st_buffer(geom, 0.0001) AS geom
FROM ar.lesy
)
SELECT count(*)
FROM ar.zeleznicnistanice as z
JOIN lesy1 as l
ON st_intersects(z.geom, l.geom)
WHERE nazev not like 'L%';
vs
CREATE TEMPORARY TABLE lesy2 AS
SELECT st_buffer(geom, 0.001) AS geom
FROM ar.lesy;
CREATE INDEX on lesy1 USING gist (geom);
SELECT count(*)
FROM ar.zeleznicnistanice as z
JOIN lesy2 as l
ON st_intersects(z.geom, l.geom)
WHERE nazev not like 'L%';
2. Kolika obcemi v ČR neprochází žádná silnice? |
241 |
SELECT count(*)
FROM ac.obcepolygony AS obce
WHERE objectid NOT IN (
SELECT DISTINCT obce.objectid
FROM ac.obcepolygony AS obce
JOIN ar.silnice_2015 AS silnice
ON st_intersects(obce.geom, silnice.geom)
);
Alternativní řešení https://www.w3schools.com/sql/sql_join_left.asp
SELECT count(*)
FROM ac.obcepolygony AS obce
LEFT JOIN ar.silnice_2015 AS sil
ON st_intersects(obce.geom, sil.geom)
WHERE sil.objectid IS NULL;
Alternativní řešení (optimalizované)
SELECT count(*)
FROM ac.obcepolygony AS obce
WHERE NOT EXISTS
(
SELECT *
FROM ar.silnice_2015 AS silnice
WHERE st_intersects(obce.geom, silnice.geom)
);
4. Vyberte silnice, které kříží vodní toky. Jaké procento z těchto silnic tvoří silnice první třídy? |
14,5% |
CREATE TEMPORARY TABLE silnice1 AS
SELECT silnice.objectid, trida
FROM ar.silnice_2015 AS silnice
JOIN ar.vodnitoky
ON st_intersects(silnice.geom, vodnitoky.geom);
SELECT round((
SELECT count(*)
FROM silnice1
WHERE trida = 3
)::numeric / (
SELECT count(*)
FROM silnice1
)::numeric * 100, 1);
nebo (CTE) https://www.root.cz/clanky/cte-a-analyticke-funkce-v-postgresql/
WITH silnice2 AS
(SELECT silnice.objectid, trida
FROM ar.silnice_2015 AS silnice
JOIN ar.vodnitoky
ON st_intersects(silnice.geom, vodnitoky.geom))
SELECT round((
SELECT count(*)
FROM silnice2
WHERE trida = 3
)::numeric / (
SELECT count(*)
FROM silnice2
)::numeric * 100, 1);
5. Kolik procent rybníků z celkového počtu leží celou svojí plochou na území Jihočeského kraje? |
41,85% |
SELECT round((
SELECT count(*)
FROM ar.vodniplochy AS v
JOIN ac.krajepolygony AS k
ON v.typ = 2
AND k.naz_cznuts3 = 'Jihočeský kraj'
AND st_within(v.geom, k.geom)
)::numeric / (
SELECT count(*)
FROM ar.vodniplochy AS v
WHERE v.typ = 2)::numeric * 100, 2);
10. Kolik vodních ploch leží alespoň částí své plochy ve vzdálenosti do 10 km od poledníku se zeměpisnou délkou 15°? |
45 |
SELECT count(*)
FROM ar.vodniplochy as v
JOIN ar.zemepisnasitwgs84 as s
ON s.delka_dd = 15
AND st_intersects(v.geom, st_buffer(st_transform(s.geom, 5514), 10e3));
3. Kolik obcí leží na hranici ČR? |
285 |
WITH cr AS
(SELECT st_boundary(geom) AS geom FROM ac.statpolygon)
SELECT count(DISTINCT kod_obec)
FROM ac.obcepolygony AS o
JOIN cr as c
ON st_intersects(o.geom, c.geom); -- st_touches()
Optimalizace
CREATE TEMPORARY TABLE cr2 (
id serial primary key,
geom geometry(Linestring, 5514)
);
INSERT INTO cr2(geom)
WITH linie AS (
SELECT st_boundary(geom) AS geom FROM ac.statpolygon
), a AS (
SELECT generate_series(0,999,1) a
)
SELECT ST_LineMerge(ST_LineSubstring(geom, a * 0.001, (a + 1) * 0.001)) AS geom
FROM a, linie;
CREATE INDEX ON cr2 USING gist(geom);
SELECT count(DISTINCT kod_obec)
FROM ac.obcepolygony AS o
JOIN cr2 as c
ON st_intersects(o.geom, c.geom);
11. Kolik obcí se dotýká alespoň jedním liniovým segmentem hranice kraje? |
1248 |
SELECT count(DISTINCT kod_obec)
FROM ac.obcepolygony AS o
JOIN ac.krajepolygony AS k
ON o.geom && k.geom
AND st_relate(o.geom, k.geom, '****1****');
Optimalizace
CREATE TEMPORARY TABLE kraje2 (
id serial primary key,
geom geometry(MultiLinestring, 5514)
);
INSERT INTO kraje2(geom)
WITH linie AS (
SELECT st_boundary(geom) AS geom FROM ac.krajepolygony
), a AS (
SELECT generate_series(0,999,1) a
)
SELECT st_multi(ST_LineMerge(ST_LineSubstring(geom, a * 0.001, (a + 1) * 0.001))) AS geom
FROM a, linie;
CREATE INDEX ON kraje2 USING gist(geom);
SELECT count(DISTINCT kod_obec)
FROM ac.obcepolygony AS o
JOIN kraje2 AS k
ON o.geom && k.geom
AND st_relate(o.geom, k.geom, '***1*****');
Další možná řešení (žádné z nich se neschoduje s ArcGISem)
WITH kraje AS
(SELECT st_boundary(geom) AS geom FROM ac.krajepolygony)
SELECT count(DISTINCT kod_obec)
FROM ac.obcepolygony AS o
JOIN kraje AS k
ON st_intersects(o.geom, k.geom);
SELECT count(DISTINCT kod_obec)
FROM ac.obcepolygony AS o
JOIN kraje2 as k
ON st_intersects(o.geom, k.geom);