Junk dimension
A junk dimension is a single dimension table that groups together several low-cardinality, otherwise-unrelated flags and indicators, to avoid cluttering a fact table with many tiny separate dimension keys.
Overview
Some fact tables end up surrounded by a handful of small, miscellaneous attributes — boolean flags, short codes, indicators — that don't belong to any natural dimension: is_gift_wrapped, payment_method, order_priority. Modeling each as its own dimension table would work, but it clutters the fact table with many extra low-value foreign keys. A junk dimension combines these unrelated, low-cardinality attributes into one dimension table, with one row per unique combination of values that actually appears in the data.
Example
Copy code
-- Instead of three separate dimension tables for three flags,
-- combine every combination that occurs into one junk dimension
CREATE TABLE dim_order_flags (
order_flags_key INTEGER PRIMARY KEY,
is_gift_wrapped BOOLEAN,
payment_method VARCHAR,
order_priority VARCHAR
);
INSERT INTO dim_order_flags VALUES
(1, true, 'credit_card', 'standard'),
(2, false, 'credit_card', 'standard'),
(3, false, 'paypal', 'expedited');
CREATE TABLE fact_orders (
order_id INTEGER PRIMARY KEY,
order_flags_key INTEGER REFERENCES dim_order_flags(order_flags_key),
revenue DECIMAL(10,2)
);
Because the attributes are low-cardinality, the junk dimension itself stays small — a handful to a few hundred rows covering every combination actually seen — even though it replaces what would otherwise be three or more separate single-attribute dimension tables and foreign keys on the fact table.
When to use one
Junk dimensions make sense when the flags are genuinely unrelated to each other and to any existing dimension, and low enough cardinality that the cross-product of their values is manageable. If an attribute is naturally part of an existing dimension (e.g., a product flag that belongs with dim_product), put it there instead of in a junk dimension.
DuckDB angle
Building a junk dimension is a straightforward SELECT DISTINCT over the flag columns you want to combine, which DuckDB executes quickly even over large fact tables:
Copy code
CREATE TABLE dim_order_flags AS
SELECT DISTINCT is_gift_wrapped, payment_method, order_priority
FROM staging_orders;
Related terms
A degenerate dimension is a dimension attribute — like an invoice or order number — that's stored directly as a column in the fact table, with no corresponding dimension table, because it has no other descriptive attributes.
Dimension table →A dimension table stores the descriptive, mostly-textual attributes — like customer name, product category, or region — that you use to filter, group, and label the measures in a fact table.
Conformed dimension →A conformed dimension is a dimension table — like a shared date or customer dimension — that is defined identically and reused across multiple fact tables or data marts, so metrics stay comparable across the warehouse.
Role-playing dimension →A role-playing dimension is a single physical dimension table, most often a date dimension, that is joined into a fact table multiple times to represent different roles, such as order date, ship date, and delivery date.
Fact table →A fact table is the central table in a dimensional model that stores numeric measures (like revenue or quantity) alongside foreign keys linking to descriptive dimension tables.
Star schema →A star schema is a dimensional data warehouse design where a central fact table of numeric measures connects directly to denormalized dimension tables, forming a shape like a star.
FAQS
A junk dimension groups several unrelated, low-cardinality flags into one small dimension table with its own key. A degenerate dimension is a value, like an order number, that's kept directly in the fact table without any dimension table at all.
