SQL Simple Pivot Pattern
Published:TIL a simple pattern for pivoting data with an SQL query using FILTER (or a
CASE WHEN clause if the FILTER keyword isn’t supported by the
database). The example
input data is from the Chinook
Database and is modeled like
this:
| InvoiceDate | BillingCountry | Total |
| ------------------- | -------------- | ----- |
| 2011-02-15 00:00:00 | Belgium | 1.98 |
| 2009-10-17 00:00:00 | Brazil | 13.86 |
| 2009-03-05 00:00:00 | USA | 3.96 |
| 2012-09-05 00:00:00 | Czech Republic | 16.86 |
| 2012-10-27 00:00:00 | India | 1.98 |
| 2012-08-27 00:00:00 | Hungary | 3.96 |
| 2011-07-25 00:00:00 | Canada | 8.91 |
| 2012-06-25 00:00:00 | USA | 1.98 |
| 2012-02-22 00:00:00 | Poland | 1.98 |
| 2013-03-05 00:00:00 | Italy | 8.91 |
A pivot query using FILTER (with a SQLite db)
SELECT strftime('%Y', InvoiceDate) AS year,
sum(Total) FILTER (WHERE BillingCountry = 'Canada') AS canada_total,
sum(Total) FILTER (WHERE BillingCountry = 'USA') AS usa_total,
sum(Total) FILTER (WHERE BillingCountry NOT IN ('Canada', 'USA')) AS rest_total
FROM Invoice
GROUP BY strftime('%Y', InvoiceDate)
or using CASE WHEN
SELECT strftime('%Y', InvoiceDate) AS year,
sum(CASE WHEN BillingCountry = 'Canada' THEN Total END) AS canada_total,
sum(CASE WHEN BillingCountry = 'USA' THEN Total END) AS usa_total,
sum(CASE WHEN BillingCountry NOT IN ('Canada', 'USA') THEN Total END) AS rest_total
FROM Invoice
GROUP BY strftime('%Y', InvoiceDate)
both create this output:
| year | canada_total | usa_total | rest_total |
| ---- | ------------ | --------- | ---------- |
| 2009 | 57.42 | 103.95 | 288.09 |
| 2010 | 76.26 | 102.98 | 302.21 |
| 2011 | 55.44 | 103.01 | 311.13 |
| 2012 | 42.57 | 127.98 | 306.98 |
| 2013 | 72.27 | 85.14 | 293.17 |