Analyser på tværs af registre

Hvert eksempel kombinerer datasæt fra mindst to myndigheder. Forespørgslerne blev sidst kørt 1. oktober 2026 mod de nyeste snapshots, og tabellerne viser det faktiske resultat.

Før du starter

Eksemplerne bruger en lille makro, dk('kilde', 'datasæt'), der altid læser det nyeste snapshot. Kør denne blok i DuckDB først. Du kan også gemme den som ~/.duckdbrc, så den indlæses automatisk.

init.sql
INSTALL spatial; LOAD spatial;
INSTALL httpfs;  LOAD httpfs;
SET s3_region = 'eu-west-1';

-- union_by_name: snapshots matches på kolonnenavn, så omdøbte eller nye kolonner i ét
-- snapshot ikke får læsningen til at fejle (kolonner, der mangler i et snapshot, bliver NULL)

-- dk('schema', 'relation') læser det nyeste snapshot af et datasæt
CREATE OR REPLACE MACRO dk(s, r) AS TABLE
  SELECT * FROM read_parquet(
    's3://gc2-parquet/centia-io/dk/schema=' || s || '/relation=' || r || '/*/*.parquet',
    union_by_name = true)
  WHERE _gc2_snapshot_date = (
    SELECT max(regexp_extract(file, '_gc2_snapshot_date=([0-9-]+)', 1))::DATE
    FROM glob('s3://gc2-parquet/centia-io/dk/schema=' || s || '/relation=' || r || '/*/*.parquet'));

-- dk_at('schema', 'relation', 'YYYY-MM-DD') læser datasættet, som det så ud på en given dato
CREATE OR REPLACE MACRO dk_at(s, r, dato) AS TABLE
  SELECT * FROM read_parquet(
    's3://gc2-parquet/centia-io/dk/schema=' || s || '/relation=' || r || '/*/*.parquet',
    union_by_name = true)
  WHERE _gc2_snapshot_date = (
    SELECT max(regexp_extract(file, '_gc2_snapshot_date=([0-9-]+)', 1))::DATE
    FROM glob('s3://gc2-parquet/centia-io/dk/schema=' || s || '/relation=' || r || '/*/*.parquet')
    WHERE regexp_extract(file, '_gc2_snapshot_date=([0-9-]+)', 1)::DATE <= dato::DATE);

-- dk_alle('schema', 'relation') læser alle snapshots; _gc2_snapshot_date er en kolonne
CREATE OR REPLACE MACRO dk_alle(s, r) AS TABLE
  SELECT * FROM read_parquet(
    's3://gc2-parquet/centia-io/dk/schema=' || s || '/relation=' || r || '/*/*.parquet',
    union_by_name = true);

Hvilke Natura 2000-områder rummer flest rødlistede arter?

278.000 fund af rødlistearter fra Naturdatabasen krydset med Miljøstyrelsens habitatområder. Et punkt-i-polygon-join på tværs af to kilder.

DuckDB-forespørgsel
SELECT h.objektnavn                         AS habitatområde,
       count(DISTINCT r.videnskabeligtnavn) AS rødlistearter,
       count(*)                             AS fund
FROM dk('naturdatabasen', 'art_roedlistearter') r
JOIN dk('danmarksarealinformation', 'habitat_omr') h
  ON ST_Intersects(r.the_geom, h.the_geom)
GROUP BY ALL
ORDER BY rødlistearter DESC
LIMIT 8;
Redigér i SQL-editoren

Kører med DuckDB i din browser. Datasættene fylder 36 MB, men kun de kolonner og dele, som forespørgslen bruger, hentes.

Resultat (12,8 s direkte fra S3 på en bærbar)

habitatområderødlistearterfund
Lovns Bredning, Hjarbæk Fjord og Skals, Simested og Nørre Ådal, Skravad Bæk1802.738
Smålandsfarvandet nord for Lolland, Guldborg Sund, Bøtø Nor, Hyllekrog-Røds1635.280
Sejerø Bugt og Saltbæk Vig1544.387
Roskilde Fjord1402.963
Vadehavet med Ribe Å, Tved Å og Varde Å vest for Varde13873.341
Løgstør Bredning, Vejlerne og Bulbjerg1373.865
Rold Skov, Lindenborg Ådal og Madum Sø1252.528
Almindingen, Ølene og Paradisbakkerne123805

Hvor mange adresser ligger på kortlagt forurenet jord?

Gældende adgangsadresser fra DAR lagt oven på V2-kortlagte arealer fra regionernes jordforureningsregister og fordelt på DAGI-kommuner.

DuckDB-forespørgsel
WITH adresser AS (
  SELECT h.id_lokalid AS id, h.kommuneinddeling, p.the_geom
  FROM dk('dar', 'husnummer') h
  JOIN dk('dar', 'adressepunkt') p ON p.id_lokalid = h.adgangspunkt
  WHERE h.status = '3'  -- gældende
)
SELECT k.navn                                     AS kommune,
       count(DISTINCT a.id)                       AS adresser,
       count(DISTINCT a.id) FILTER (v.gid NOTNULL) AS på_v2_jord,
       round(100.0 * på_v2_jord / adresser, 1)    AS procent
FROM adresser a
JOIN dk('dagi', 'kommuneinddeling') k ON k.id_lokalid = a.kommuneinddeling
LEFT JOIN dk('dkjord', 'dkjord_v2') v ON ST_Intersects(a.the_geom, v.the_geom)
GROUP BY ALL
ORDER BY procent DESC
LIMIT 8;
Redigér i SQL-editoren

Kører med DuckDB i din browser. Datasættene fylder 1,3 GB, men kun de kolonner og dele, som forespørgslen bruger, hentes. Store datasæt kan tage et til to minutter i browseren. Med DuckDB på din egen maskine tog den 26,4 s.

Resultat (26,4 s direkte fra S3 på en bærbar)

kommuneadresserpå v2 jordprocent
København83.95910.69812,7
Frederiksberg9.5841.11611,6
Tårnby14.4131.0197,1
Rødovre12.6516054,8
Gladsaxe19.8369174,6
Brøndby9.9843863,9
Herlev10.6483713,5
Hillerød20.4966703,3

Hvor står landets ældste bygningsmasse?

4,8 millioner opførte bygninger fra BBR grupperet på kommunekode og beriget med kommunenavne fra DAGI. Et almindeligt join, men uden en eneste API-kaldsrunde.

DuckDB-forespørgsel
SELECT k.navn                                             AS kommune,
       count(*)                                           AS bygninger,
       median(try_cast(b.byg026opførelsesår AS INT))::INT AS median_opførelsesår,
       count(*) FILTER (try_cast(b.byg026opførelsesår AS INT) < 1900) AS før_1900
FROM dk('bbr', 'bygning') b
JOIN dk('dagi', 'kommuneinddeling') k USING (kommunekode)
WHERE b.status = '6'  -- opført
  AND try_cast(b.byg026opførelsesår AS INT) BETWEEN 1000 AND 2030
GROUP BY ALL
ORDER BY median_opførelsesår
LIMIT 8;
Redigér i SQL-editoren

Kører med DuckDB i din browser. Datasættene fylder 1,3 GB, men kun de kolonner og dele, som forespørgslen bruger, hentes. Store datasæt kan tage et til to minutter i browseren. Med DuckDB på din egen maskine tog den 15,6 s.

Resultat (15,6 s direkte fra S3 på en bærbar)

kommunebygningermedian opførelsesårfør 1900
Ærø11.57619244.006
Frederiksberg9.49119341.797
Gentofte31.83819367.157
København82.259195011.613
Bornholm62.479195115.735
Lolland60.199195514.446
Lyngby-Taarbæk23.61819581.670
Langeland26.24219604.783

Hvor er der flest ladepunkter pr. adresse?

Kommunernes registrering af ladestandere i GeoFA placeret rumligt i DAGI-kommuner og sat i forhold til antallet af gældende adresser i DAR.

DuckDB-forespørgsel
WITH lade AS (
  SELECT k.id_lokalid, sum(l.antal_ladepunkter)::INT AS ladepunkter
  FROM dk('geofa', 't_5607_ladefacilitet') l
  JOIN dk('dagi', 'kommuneinddeling') k ON ST_Intersects(l.the_geom, k.the_geom)
  WHERE l.statuskode = 3
  GROUP BY ALL
), adr AS (
  SELECT kommuneinddeling AS id_lokalid, count(*) AS adresser
  FROM dk('dar', 'husnummer') WHERE status = '3' GROUP BY ALL
)
SELECT k.navn                                           AS kommune,
       lade.ladepunkter,
       adr.adresser,
       round(1000.0 * lade.ladepunkter / adr.adresser, 1) AS pr_1000_adresser
FROM dk('dagi', 'kommuneinddeling') k
JOIN lade USING (id_lokalid)
JOIN adr  USING (id_lokalid)
ORDER BY pr_1000_adresser DESC
LIMIT 8;
Redigér i SQL-editoren

Kører med DuckDB i din browser. Datasættene fylder 575 MB, men kun de kolonner og dele, som forespørgslen bruger, hentes.

Resultat (16,7 s direkte fra S3 på en bærbar)

kommuneladepunkteradresserpr 1000 adresser
Høje-Taastrup1.60217.70190,5
København6.70683.95979,9
Frederiksberg7549.58478,7
Tårnby61814.41342,9
Albertslund47511.38441,7
Billund64716.41139,4
Brøndby3899.98439
Herlev38410.64836,1

Hvilke lokalplaner er vedtaget siden 17. september?

Det samme datasæt læst på to datoer. Planer i det nyeste snapshot, som ikke fandtes i snapshottet fra 17. september, er kommet til siden. Skift datoen for at se en anden periode.

DuckDB-forespørgsel
SELECT ny.kommunenavn                                    AS kommune,
       ny.plannavn                                       AS lokalplan,
       strptime(ny.datovedt::VARCHAR, '%Y%m%d')::DATE    AS vedtaget
FROM dk('plandatadk', 'pdk_lokalplan_vedtaget_v') ny
ANTI JOIN dk_at('plandatadk', 'pdk_lokalplan_vedtaget_v', '2026-09-17') gammel
  USING (planid)
ORDER BY vedtaget DESC, kommune;
Redigér i SQL-editoren

Kører med DuckDB i din browser. Datasættene fylder 41 MB, men kun de kolonner og dele, som forespørgslen bruger, hentes.

Resultat (6 s direkte fra S3 på en bærbar)

kommunelokalplanvedtaget
HaderslevSolenergianlæg ved Strandelhjørn2026-09-29
HjørringRegulering af sekundær bebyggelse ved Høngårds Ager (tillæg til lokalplan 10.000-04)2026-09-29
NyborgOmråde til ladepark ved Hjulby2026-09-28
FavrskovTillæg nr. 1 til lokalplan nr. 582026-09-25
TønderOphævelse af lokalplan 7.332026-09-25
NordfynsBogense Forsyning2026-09-24
NordfynsBryggergården2026-09-24
TønderBredebro II solenergipark2026-09-24
TønderHøjspændingssamlestation ved Galgemark, Bredebro2026-09-24
FrederikshavnStrandby Havn2026-09-23
GladsaxeOffentlige formål ved Pilegårdsvej i Mørkhøj2026-09-23
ThistedOphævelse af lokalplan 1.33 - Nordatlantens Hus, Hanstholm2026-09-23
GribskovLokalplan for en del af Ørby Landsby2026-09-22
KoldingVed Lærkevej - et område til offentlige formål2026-09-22
Ringkøbing-SkjernOmråde til offentlige formål ved Idrætsvej, Lyne2026-09-22
Ringkøbing-SkjernOmråde til rekreative formål ved Nyhavn, Søndervig2026-09-22
MariagerfjordDøgninstitution ved Ølsvej i Hobro2026-09-18
GlostrupDaginstitution på Mosetoften2026-09-16
Høje-TaastrupFor et område mellem Hovedgaden og Kallerupvej2026-09-16
AalborgHøjspændingsstation - Nordjyllandsværket2026-09-15
AllerødVassingerød Erhvervsområde2026-09-15
HerningBoligområde ved Engholm Søpark i Herning2026-09-15
EsbjergTæt - Lav boligbebyggelse ved Andrupgård, Esbjerg Ø2026-09-14
GreveTillæg nr. 2 til Lokalplan nr. 12.50 for strandvejsområdet2026-09-14
LangelandNyt boligområde i Bagenkop2026-09-14
FrederikssundLokalplan for Banegrav ved Bonderup2026-09-08
GladsaxeStengård Skole2026-08-26
SønderborgSolcelleanlæg ved Lavensby, Nordborg2026-08-26
HvidovreErhvervsområdet ved Gungevej, Arnold Nielsens Boulevard, Bibliotekvej og Høvedstensvej2026-08-25