Conventions
A few conventions apply across the whole share. Reading this page first will help understand some common tricks in the data model.
The core key: entity, question, year
Almost every data table answers a question about a company in a period:
entity_id— who. Joins toentities.question_id(or its string form,canonical_question_id) — what. Joins toquestions.year— when. The fiscal year the value relates to. The exact period is given by thestart/end(orstart_date/end_date) columns, since company fiscal years do not always align with calendar years. See Assigning years for more details on how we allocate this.
Versioned tables: always filter to the current view
The data tables in the share are append-only and versioned. When a value is restated — for example a company restates its emissions, or our research process refines a number — we do not overwrite the old row. Instead the old row is closed and a new row is written. Every versioned table carries:
| Column | Type | Description |
|---|---|---|
valid_from | TIMESTAMP_TZ | When this version of the row became current |
valid_to | TIMESTAMP_TZ | When this version was superseded. Open-ended for the live row |
is_current | BOOLEAN | TRUE for the latest version of the row |
Unless you are doing point-in-time analysis, always filter
is_current = TRUE:
SELECT *
FROM NET_PURPOSE.OUTCOMES.ALL_DATA
WHERE is_current = TRUE
AND entity_id = 12345;Point-in-time queries
Because the full history is kept, you can reconstruct exactly what the data
looked like on any past date. A row was live at time t when
valid_from <= t AND valid_to > t:
SELECT *
FROM NET_PURPOSE.OUTCOMES.ALL_DATA
WHERE entity_id = 12345
AND valid_from <= '2025-06-30'::TIMESTAMP_TZ
AND valid_to > '2025-06-30'::TIMESTAMP_TZ;For any given table, data-triplet and t this should be a unique row.
This is useful for backtesting: it removes look-ahead bias by showing only what was known at the time.
Reference tables such as questions, units, segments, taxonomy and
reporting_standards are plain lookup tables and do not need the is_current filter.
Data classes: reported, derived, estimated
In the combined data-set schema (Revenue & SDI and Outcomes) all rows carry a label describing from which foundation data-set they were produced:
data_origin_class_id | Label | Meaning |
|---|---|---|
| 1 | Reported | Disclosed directly by the company in a public source |
| 2 | Derived | Calculated from reported values (for example a ratio or a sum of segments) |
| 3 | Estimated | Modelled by Net Purpose where no disclosure exists |
Every row in all_data carries a data_origin_class_id, so you can include or
exclude estimated data with a single filter.
Years and year_rank
Companies disclose on different schedules, so “the latest year” differs by
entity. Tables that serve latest-value workflows carry a year_rank column:
year_rank = 1 is the most recent year available for that entity, 2 the year before, and so on. To get the
latest value per company, filter year_rank = 1 instead of hard-coding a year.
Units and currencies
Numeric values are standardised before they reach the share: each question
has a standard unit (see questions.unit_id joined to units), and
monetary values are converted to USD. Where a table also exposes the
originally reported value and unit (for example datapoints), the
reported_value / reported_unit_id columns hold the pre-standardisation
figures. These unit tables include units representing orders of magnitude of the base unit (e.g million metric tonnes) which is treated as a separate unit for reporting.
Identifiers
entity_id is the Net Purpose identifier and is stable across the whole
share. To map to your own universe, join your ISINs to the primary_isin
column on entities, or use entity_identifiers for the other schemes
(CUSIP, SEDOL, PermID, FIGI, ticker, LEI) per entity.
Year assignment
The year on a datapoint is not simply the calendar year of its end date.
Because fiscal years vary between companies, we assign each datapoint to a
fiscal year relative to the entity’s own reporting schedule.
The reporting date
Every entity records a reporting_day and reporting_month — the day and
month on which its fiscal year ends. For a given datapoint (a fact or a
datapoint) we build a nominal reporting date by combining the entity’s
reporting_day and reporting_month with the year of the datapoint’s end
date:
reporting_date = date(year(end_date), reporting_month, reporting_day)For example, an entity with reporting_day = 31, reporting_month = 12 and a
datapoint ending 2025-11-15 has a nominal reporting date of 2025-12-31.
Assigning the year
We then compare the datapoint’s end_date to this reporting date. There is a
30-day tolerance window before the reporting date to absorb minor reporting
variations:
Where the end_date falls | Year assigned |
|---|---|
| On or after the reporting date | Year of the reporting date |
| Within the 30 days before the reporting date | Year of the reporting date |
| More than 30 days before the reporting date | The prior year |
In other words, any end_date later than reporting_date - 30 days is
assigned to the reporting date’s year; anything earlier falls back to the year
before.
January reporting dates
If the reporting date falls in January, we treat it as belonging to the
previous year. This reflects the convention that a fiscal year ending in early
January really relates to the year that just closed. For example, a reporting
date of 2026-01-31 is assigned to 2025.