Transform columns into rows — the inverse of PIVOT. Takes values spread across multiple columns and normalizes them into a key-value row structure. Useful for reshaping wide, denormalized data.
The inverse of pivot: transforms columns into rows, useful for normalizing denormalized reports back into a normalized form for analysis. SQL Server has native UNPIVOT; other databases use UNION ALL or table-valued constructors.
| Database System | Support Status | Since Version | Notes |
|---|---|---|---|
| MySQL | ✗ Not Supported | — | No UNPIVOT operator. The universal UNION ALL workaround works in all MySQL versions. In MySQL 8.0+, a JSON-based approach using JSON_TABLE can dynamically unpivot a JSON object into rows. |
| PostgreSQL | ✗ Not Supported | — | PostgreSQL has no UNPIVOT keyword. The idiomatic approach uses a VALUES clause with a CROSS JOIN LATERAL or a CROSS JOIN (VALUES ...) to enumerate the column-to-row mapping. This is concise and avoids repeating the FROM clause for each union branch. |
| SQL Server | ✓ Supported | 2005 | UNPIVOT operator available since SQL Server 2005. Syntax mirrors PIVOT: specify the value column name, the key column name, and the list of source columns. UNPIVOT automatically excludes NULL values — rows where the source column is NULL do not appear in the output. For dynamic column lists (unknown at query time), use dynamic SQL. |
| Oracle | ✓ Supported | 11g | UNPIVOT operator available since Oracle 11g. Supports INCLUDE NULLS / EXCLUDE NULLS clause (EXCLUDE NULLS is the default, unlike the behavior implied by UNION ALL which includes NULLs unless filtered). Can unpivot multiple value columns simultaneously. |
| SQLite | ✗ Not Supported | — | No UNPIVOT operator. Use the UNION ALL workaround or, in SQLite 3.8.3+, the VALUES table constructor with a CROSS JOIN. |
Only SQL Server (2005+) and Oracle (11g+) have a native UNPIVOT operator. The most portable alternative is the UNION ALL pattern — one SELECT per column being unpivoted. For long column lists this becomes verbose; the VALUES + CROSS APPLY/CROSS JOIN approach (SQL Server, PostgreSQL, SQLite 3.8.3+) is more concise and scans the source table only once. SQL Server's UNPIVOT automatically excludes NULLs; Oracle's UNPIVOT defaults to EXCLUDE NULLS but can be changed with INCLUDE NULLS. The CROSS APPLY (VALUES ...) pattern in SQL Server is generally preferred over the UNPIVOT keyword because it handles multiple value columns and is easier to extend.
No UNPIVOT operator. The universal UNION ALL workaround works in all MySQL versions. In MySQL 8.0+, a JSON-based approach using JSON_TABLE can dynamically unpivot a JSON object into rows.
PostgreSQL has no UNPIVOT keyword. The idiomatic approach uses a VALUES clause with a CROSS JOIN LATERAL or a CROSS JOIN (VALUES ...) to enumerate the column-to-row mapping. This is concise and avoids repeating the FROM clause for each union branch.
UNPIVOT operator available since SQL Server 2005. Syntax mirrors PIVOT: specify the value column name, the key column name, and the list of source columns. UNPIVOT automatically excludes NULL values — rows where the source column is NULL do not appear in the output. For dynamic column lists (unknown at query time), use dynamic SQL.
UNPIVOT operator available since Oracle 11g. Supports INCLUDE NULLS / EXCLUDE NULLS clause (EXCLUDE NULLS is the default, unlike the behavior implied by UNION ALL which includes NULLs unless filtered). Can unpivot multiple value columns simultaneously.
No UNPIVOT operator. Use the UNION ALL workaround or, in SQLite 3.8.3+, the VALUES table constructor with a CROSS JOIN.