Workplace safety — injuries province by province
Workplace injuries reported to INAIL, province by province: the trend over the years, fatal cases, the sectors, and the map of Italy with the rate per 1,000 inhabitants. Official 2020-2024 data, joined on its own with the ISTAT population.
data space «sicurezza-lavoro» — the suite’s glue: on your device, multi-user with one invite (link or QR), end-to-end encrypted.
What it records
- Province code
Composed of 3 micro apps
One job each, over the same data: every micro app reads and writes the shared data space “sicurezza-lavoro” (with your consent, asked on first open). Everything stays on your device — and with a single invite the whole suite goes multi-user, end-to-end encrypted.
How it works
This is a Reactive app: a plain text document that your browser turns into a working app — forms, live data, tables, statistics and even charts, with nothing to install or configure.
- Use it right away. Hit “Use this app”: it opens right in your browser, ready to go, with data saved only on your device.
- Your data stays yours. Everything is stored locally on your device, kept separate for each app: no account, no server, nothing to set up.
- Make it your own. The text below is the entire app: copy it, tweak fields, views and words, and your changes become interactive instantly.
- Share it as a file. An app is a simple file: save it, export it or share it with a link; and with encrypted collaboration several people edit the same data in real time.
The app’s source
# ⛑️ Workplace safety
Workplace injuries reported to INAIL, province by province: the trend over the
years, fatal cases, the sectors, and the map of Italy with the rate per 1,000
inhabitants. Official 2020-2024 data, joined on its own with the ISTAT
population.
:::::page{title="Your province" icon="📈"}
## The trend in your province
Province code (e.g. `BO`, `MI`, `TO`, `NA`, `PA`).
::input[prov]{value="BO" placeholder="Province code"}
::od-query{into="trend" sql="SELECT anno AS anno, sum(infortuni) AS infortuni FROM inail_infortuni WHERE sigla = '{#prov}' GROUP BY anno ORDER BY anno"}
::chart-line{data="trend" x="anno" y="infortuni" height="16rem"}
**Fatal cases** deserve their own chart (the scale differs by three orders of
magnitude):
::od-query{into="mortali" sql="SELECT anno AS anno, sum(mortali) AS morti FROM inail_infortuni WHERE sigla = '{#prov}' GROUP BY anno ORDER BY anno"}
::chart-bar{data="mortali" x="anno" y="morti" height="14rem"}
:::table{path="trend" headers="Year,Reported injuries" pagesize="6" search="false"}
{anno} | {infortuni}
:::
:::::
:::::page{title="The sectors" icon="🏭"}
## Where injuries happen
The 2024 reports in the chosen province, by insurance sector: industry and
services, agriculture, the State account (schools and public administration).
::od-query{into="settori" sql="SELECT gestione AS gestione, sum(infortuni) AS infortuni FROM inail_infortuni WHERE sigla = '{#prov}' AND anno = 2024 GROUP BY gestione ORDER BY infortuni DESC"}
::chart-pie{data="settori" label="gestione" value="infortuni" height="16rem"}
And the gender split, on the same data:
::od-query{into="genere" sql="SELECT CASE genere WHEN 'M' THEN 'Uomini' WHEN 'F' THEN 'Donne' ELSE genere END AS genere, sum(infortuni) AS infortuni FROM inail_infortuni WHERE sigla = '{#prov}' AND anno = 2024 GROUP BY 1 ORDER BY 2 DESC"}
::chart-pie{data="genere" label="genere" value="infortuni" height="14rem"}
:::::
:::::page{title="The map" icon="🗺️"}
## The injury rate, province by province
Each province colored by **injuries per 1,000 inhabitants** (2024): the
numerator is INAIL, the denominator the ISTAT population. Hover for the value.
::od-query{into="mappa" sql="SELECT p.provincia AS provincia, p.geojson AS geojson, t.tasso AS tasso FROM istat_confini_province p JOIN (SELECT i.sigla, round(1000.0 * sum(i.infortuni) / ab.pop, 1) AS tasso FROM inail_infortuni i JOIN (SELECT c.sigla, sum(po.popolazione) AS pop FROM istat_confini_comuni c JOIN istat_popolazione po ON po.codice_istat = c.codice_istat GROUP BY 1) ab ON ab.sigla = i.sigla WHERE i.anno = 2024 GROUP BY i.sigla, ab.pop) t ON t.sigla = p.sigla" limit="150"}
:::map{path="mappa" geojson="geojson" fill="tasso" height="28rem"}
**{provincia}** — {tasso} injuries per 1,000 inhabitants
:::
The rate per inhabitant (not per worker) is an indicator of *impact on the
territory*: manufacturing and agricultural provinces stand out.
:::::
---
The data are the **INAIL injury reports** (Open Data, CC BY 4.0), aggregated
by province, year, sector and gender, plus the ISTAT **population** and
**boundaries** (CC BY 4.0). The sources join on their own via the province
code. A *reported* injury is not necessarily a *recognized* one: for rigorous
comparisons consult INAIL's consolidated data too. None of your data leaves
the device.