---
title: "Wide table"
description: "A wide table is a table with a large number of columns, typically produced by denormalizing and flattening related data together, common in analytics and columnar data warehouses."
canonical: "https://motherduck.com/glossary/wide-table/"
related:
  - title: "Understanding DuckLake: A Table Format with a Modern Architecture | MotherDuck"
    url: "https://motherduck.com/videos/understanding-ducklake-a-table-format-with-a-modern-architecture/"
  - title: "CREATE TABLE | MotherDuck Docs"
    url: "https://motherduck.com/docs/sql-reference/duckdb-sql-reference/duckdb-statements/create-table/"
  - title: "Internal vs. External Storage: What's the Limit of External Tables?"
    url: "https://motherduck.com/blog/internal-vs-external-storage-whats-the-limit-of-external-tables/"
---

# Wide table

> A wide table is a table with a large number of columns, typically produced by denormalizing and flattening related data together, common in analytics and columnar data warehouses.

## Overview

A wide table packs many columns — sometimes hundreds — into a single table, usually by flattening what would otherwise be several normalized or dimensional tables into one. Instead of joining a fact table to five dimension tables at query time, a wide table pre-joins everything once, so every attribute a report might need is already sitting in one row.

Wide tables trade storage and load-time complexity for query-time simplicity: no joins are needed, which is especially valuable for BI tools and less SQL-fluent users who just want to filter and aggregate a single table. The trade-off is redundancy (the same dimension value repeats across many fact rows) and less flexibility if the underlying grain or relationships change.

<glossary-callout guide="duckdb-cheatsheet-full" />

### Example

```sql
-- A wide, pre-joined table instead of fact + several dimensions
CREATE OR REPLACE TABLE sales_wide AS
SELECT
    f.order_id, f.revenue, f.quantity,
    c.customer_name, c.region, c.segment,
    p.product_name, p.category, p.department,
    d.full_date, d.quarter, d.fiscal_year
FROM fact_sales f
JOIN dim_customer c USING (customer_key)
JOIN dim_product  p USING (product_key)
JOIN dim_date     d USING (date_key);

SELECT region, category, SUM(revenue) AS revenue
FROM sales_wide
GROUP BY ALL;
```

### Why columnar engines favor wide tables

Row-oriented databases pay a real cost for wide tables, since scanning any single column still means reading full rows off disk. Columnar engines don't have that problem — each column is stored (and compressed) separately, so a query touching 3 of a table's 200 columns only reads those 3. That's part of why wide, denormalized tables are common in modern analytical warehouses: the traditional storage-efficiency argument for keeping tables narrow and normalized mostly doesn't apply.

### DuckDB angle

DuckDB's columnar storage is exactly what makes wide tables practical: adding more columns to a table doesn't slow down a query that ignores them, and repeated values in denormalized columns (like a repeated `region` string) compress well. Building a wide table with `CREATE OR REPLACE TABLE ... AS SELECT` from a star schema, as above, is a common way to hand analysts or BI tools a single, join-free table in DuckDB or MotherDuck.
