sqlcmd.net validated sql reference
advanced reshaping MySQL MariaDB SQL Server PostgreSQL SQLite

Convert Columns to Rows With UNPIVOT

Reshape a wide table by turning multiple columns into key-value row pairs — the inverse of a PIVOT operation.

Docker-validated Not currently validation-green

Convert per-quarter sales columns into one row per quarter

The original table has one row per region with three value columns. After unpivoting, each region produces three rows — one per quarter — with a quarter label column and a single revenue value column. The UNION ALL approach reads the source table three times (once per column), which is fine for small tables. The SQL Server UNPIVOT and PostgreSQL LATERAL approaches read the table once.

MySQL MariaDB SQLite
Engine-specific syntax
Setup
CREATE TABLE sales (region VARCHAR(50), q1 INT, q2 INT, q3 INT);

INSERT INTO
  sales
VALUES
  ('East', 100, 120, 140),
  ('West', 80, 95, 110);
SQL
SELECT
  region,
  'q1' AS quarter,
  q1 AS revenue
FROM
  sales
UNION ALL
SELECT
  region,
  'q2',
  q2
FROM
  sales
UNION ALL
SELECT
  region,
  'q3',
  q3
FROM
  sales
ORDER BY
  region,
  quarter;
regionquarterrevenue
Eastq1100
Eastq2120
Eastq3140
Westq180
Westq295
Westq3110
SQL Server
Engine-specific syntax
Setup
CREATE TABLE sales (region VARCHAR(50), q1 INT, q2 INT, q3 INT);

INSERT INTO
  sales
VALUES
  ('East', 100, 120, 140),
  ('West', 80, 95, 110);
SQL
SELECT
  region,
  quarter,
  revenue
FROM
  sales UNPIVOT (revenue FOR quarter IN (q1, q2, q3)) AS u
ORDER BY
  region,
  quarter;
regionquarterrevenue
Eastq1100
Eastq2120
Eastq3140
Westq180
Westq295
Westq3110
PostgreSQL
Engine-specific syntax
Setup
CREATE TABLE sales (region VARCHAR(50), q1 INT, q2 INT, q3 INT);

INSERT INTO
  sales
VALUES
  ('East', 100, 120, 140),
  ('West', 80, 95, 110);
SQL
SELECT
  region,
  quarter,
  revenue
FROM
  sales
  CROSS JOIN LATERAL (
    VALUES
      ('q1', q1),
      ('q2', q2),
      ('q3', q3)
  ) AS u (quarter, revenue)
ORDER BY
  region,
  quarter;
regionquarterrevenue
Eastq1100
Eastq2120
Eastq3140
Westq180
Westq295
Westq3110

SQL Server uses native UNPIVOT. PostgreSQL uses CROSS JOIN LATERAL (VALUES …). MySQL, MariaDB, and SQLite use UNION ALL. All produce an identical six-row result.

Where this command helps.

  • converting a quarterly-columns layout into a time-series of rows for analysis
  • normalising denormalised multi-column data before loading into a fact table

What the command is doing.

UNPIVOT transforms a row with many value columns (e.g. q1, q2, q3) into multiple rows, each containing a column-name label and the corresponding value. SQL Server has native UNPIVOT syntax. PostgreSQL and SQLite use CROSS JOIN LATERAL (VALUES …) to produce the same result without a dedicated keyword. MySQL and MariaDB, which lack lateral joins with correlated value constructors, use UNION ALL to manually stack the columns.