Vzzarr
Vzzarr

Reputation: 5650

How to pivot without using PIVOT functions in SQL?

I'd like to pivot a table without using any PIVOT function but using pure SQL only (let's say PostgreSQL syntax for example).

So having this data-set as an example:

Order |   Element | Value |
---------------------------
1     | Item      | Bread |
1     | Quantity  |  3    |
1     | TotalCost |  3,30 |
2     | Item      | Pizza |
2     | Quantity  |  2    |
2     | TotalCost |  10   |
3     | Item      | Pasta |
3     | Quantity  |  5    |
3     | TotalCost |  2,50 |

I'd expect to pivot on the Order column and having somenthing like:

Order | Item | Quantity | TotalCost |
-------------------------------------
1     | Bread |    3    |    3,30   |
2     | Pizza |    2    |    10     |
3     | Pasta |    5    |    2,50   |

How would I achieve that, once again, without using any pivot function?

Upvotes: 2

Views: 705

Answers (2)

Vzzarr
Vzzarr

Reputation: 5650

Solution A

using CASE WHEN statements:

SELECT Order, 
       MAX(CASE WHEN Element = 'Item' THEN Value END) AS Item, 
       MAX(CASE WHEN Element = 'Quantity' THEN Value END) AS Quantity, 
       MAX(CASE WHEN Element = 'TotalCost' THEN Value END) AS TotalCost
FROM MyTable
GROUP BY 1

Solution B

Using self LEFT JOINs:

SELECT A.Order, A.Item, B.Quantity, C.TotalCost
FROM
    (SELECT Order, Value as Item
    FROM MyTable
    WHERE Element = 'Item') as A
    LEFT JOIN
    (SELECT Order, Value as Quantity
    FROM MyTable
    WHERE Element = 'Quantity') as B ON A.Order = B.Order
    LEFT JOIN
    (SELECT Order, Value as TotalCost
    FROM MyTable
    WHERE Element = 'TotalCost') as C ON B.Order = C.Order

The latter might not be as much as efficient but there are use case in which might come useful.

Upvotes: 2

Gordon Linoff
Gordon Linoff

Reputation: 1269503

In Postgres, you would use FILTER:

SELECT Order, 
       MAX(Value) FILTER (WHERE Element = 'Item') AS Item, 
       MAX(Value) FILTER (WHERE Element = 'Quantity') AS Quantity, 
       MAX(Value) FILTER (WHERE Element = 'TotalCost') AS TotalCost
FROM MyTable
GROUP BY 1;

Note that ORDER is a SQL Keyword so it is a bad choice for a column name.

Upvotes: 1

Related Questions