Check that a decomposition sums to its parent

Numbers checked against the live data on

This page shows queries.

Add only the rows whose parent_relation is sums_to_parent, and compare that sum with the parent row: never add the parent to its own children. For ADEME's butane (Europe, per kWh), the 2014 vintage splits exactly, 0.22968 + 0.0378 = 0.26748 kg CO2e per kWh.

The query#

A decomposition shares one root_slug. This query lists the parent and its children for every vintage, with the sum of the children beside each row.

Show the SQL
SELECT reference_year,
       system_boundary,
       parent_relation,
       is_top_parent,
       value_co2e_native,
       round((sum(value_co2e_native) FILTER (WHERE parent_relation = 'sums_to_parent')
              OVER (PARTITION BY reference_year))::numeric, 5) AS children_sum
FROM open_ef.factors_flat
WHERE library = 'ademe'
  AND root_slug = 'ef-ademe-butane_maritime_included-europe-kwh-well_to_use-53be0cf1'
  AND is_default_indicator
ORDER BY reference_year, is_top_parent DESC, system_boundary;
reference_year system_boundary parent_relation is_top_parent value_co2e_native children_sum
2014 well_to_use NULL true 0.26748 0.26748
2014 combustion sums_to_parent false 0.22968 0.26748
2014 upstream_fuel sums_to_parent false 0.0378 0.26748
2019 well_to_use NULL true 0.269 0.26920
2019 combustion sums_to_parent false 0.23 0.26920
2019 upstream_fuel sums_to_parent false 0.0392 0.26920

The 2014 vintage adds up to the parent exactly. The 2019 vintage, the current default, is off by 0.0002 because the publisher rounds each printed figure on its own. Treat a gap of that size as rounding, and report the parent's printed total.

The query filters on is_default_indicator but not on is_latest_activity_year, so that both vintages show. To read one vintage only, add AND is_latest_activity_year (the current one) or a year filter, as in Get the value for a past year.

Why it works#

Why it works. The parent row (is_top_parent, no parent_relation) is the total. combustion and upstream_fuel are parts of it. Filtering on parent_relation = 'sums_to_parent' adds the parts and leaves the total out. Summing every row of the root_slug would count the butane twice.

Watch out. Only sums_to_parent children are addends. A contained_by_parent child is a nested envelope, a smaller boundary inside the parent's, so it is not a part to add, and a reported_beside_parent row (EN 15804 module D) is reported next to the total and never added to it. In any aggregate over many factors, keep WHERE is_top_parent so that no child is counted beside its parent.

Which total to report#

The two parts exist because reporting standards disagree on where the line falls. Under the GHG Protocol, combustion is Scope 1 and the upstream part is Scope 3.3, reported apart. ISO 14083 wants the well-to-use total. On factors_flat, is_top_parent AND system_boundary = 'well_to_use' gives the ISO 14083 view, and the GHG Protocol view is that parent's parent_relation = 'sums_to_parent' children, reported apart. Do not read NOT is_derived as the GHG Protocol filter: it only says the publisher printed the total itself, which ADEME does and DESNZ does not.