Skip to content

Fact Types by Additivity

Fact tables can be classified based on how they behave when aggregated across dimensions:

Additive Facts

Additive facts can be safely summed across all dimensions. They are the easiest facts to aggregate.

For example, sales_amount can be summed across products, customers, stores and time.

sale_dateproductstoresales_amount
Jan 1LaptopStore A$1,000
Jan 1PhoneStore A$500
Jan 2LaptopStore B$1,200
Jan 2PhoneStore B$700

The total sales amount can be calculated across any combination of these dimensions.

Semi-Additive Facts

Semi-additive facts can be summed across some dimensions but not others. This commonly occurs with measurements that represent a point-in-time state, where summing across time would produce a meaningless result.

For example, an account balance can be summed across customers on a given day, but adding account balances across multiple days is not meaningful.

snapshot_datecustomeraccount_balance
Jan 1Alice$1,000
Jan 1Bob$2,000
Jan 2Alice$1,500
Jan 2Bob$2,500

On Jan 1, the total balance is $3,000. However, summing Jan 1 and Jan 2 balances to get $7,000 would be meaningless.

Non-Additive Facts

Non-additive facts cannot be meaningfully summed across dimensions. When aggregated, they usually must be recalculated from their underlying additive or semi-additive components.

A good approach is to always store the additive building blocks of these non-additive facts in your database. When summarizing data, you add those basic components together first and use the combined totals to calculate the final non-additive fact.

Common examples include percentages, ratios and unit prices. Consider profit margin across two stores:

storerevenueprofitprofit_margin
North$10,000$2,00020%
South$1,000$50050%

Summing the margins gives 70%, which is meaningless. The correct total margin comes from summing the additive components first: $2,500 profit ÷ $11,000 revenue = 22.7%.

Derived Measures (e.g., Year-to-Date)

Business users often request derived or cumulative values like year-to-date (YTD) directly in a fact table. It is hard to argue against a single request, but YTD requests can easily morph into "YTD at the close of the fiscal period" or "fiscal period to date".

A more reliable, extensible way to handle these assorted requests is to calculate the YTD metrics dynamically in the BI applications or OLAP cube rather than storing them as physical facts.

date_keyproduct_keydaily_sales_amount
Jan 1Laptop$1,000
Jan 2Laptop$1,500

TIP

Rely on your BI tool's analytical functions (e.g., window functions in SQL, or time intelligence in DAX) to compute the YTD rollups based on atomic additive facts like daily_sales_amount.