The portable way to pivot is conditional aggregation — one SUM(CASE WHEN …) per output column. This works in every dialect:
SELECT
product,
SUM(CASE WHEN quarter = 'Q1' THEN amount END) AS q1,
SUM(CASE WHEN quarter = 'Q2' THEN amount END) AS q2,
SUM(CASE WHEN quarter = 'Q3' THEN amount END) AS q3,
SUM(CASE WHEN quarter = 'Q4' THEN amount END) AS q4
FROM sales
GROUP BY product;
BigQuery, Snowflake and DuckDB also have a dedicated PIVOT operator:
-- BigQuery / Snowflake / DuckDB
SELECT *
FROM sales
PIVOT (SUM(amount) FOR quarter IN ('Q1', 'Q2', 'Q3', 'Q4'));
No PIVOT in MySQL, PostgreSQL or SQLite. Use the
CASEform above. (PostgreSQL hascrosstab()but it needs thetablefuncextension and rigid column typing — theCASEform is simpler and needs nothing installed.) The pivot column values must be known in advance; for a dynamic set of columns you have to build the SQL string in your app.