Pivot & Unpivot
Pivot folds a binding stream into a single tuple; unpivot ranges over attribute-value pairs of a tuple — dual operations for reshaping data.
Pivot
Pivot Builds
Pivot builds one object with an attribute per input row.
SQL
create table T;
create table prices;
insert into prices ({"sym": "amzn", "price": 1900}, {"sym": "goog", "price": 1120});
pivot p.price at p.sym from prices as p;
Result
[
{ "amzn": 1900, "goog": 1120 }
]
Pivot Inverts
Pivot inverts unpivot over the same value.
SQL
create table T;
pivot price at sym from unpivot {"a": 1, "b": 2, "c": 3} as price at sym;
Result
[
{ "a": 1, "b": 2, "c": 3 }
]
Pivot Over
Pivot over an empty stream yields a single empty object.
SQL
create table T;
create table empty_t;
pivot p.price at p.sym from empty_t as p;
Result
[
{}
]
Wins Duplicate
A repeated attribute name is last-wins.
SQL
create table T;
create table d;
insert into d ({"k": "x", "v": 1}, {"k": "x", "v": 2});
pivot e.v at e.k from d as e;
Result
[
{ "x": 2 }
]
String Name
A row whose AT name is not a string contributes no attribute.
SQL
create table T;
create table m;
insert into m ({"k": "ok", "v": 1}, {"k": 5, "v": 2});
pivot e.v at e.k from m as e;
Result
[
{ "ok": 1 }
]
Where Filters
Where filters which rows contribute attributes.
SQL
create table T;
create table prices;
insert into prices ({"sym": "a", "price": 1}, {"sym": "b", "price": 2}, {"sym": "c", "price": 3});
pivot p.price at p.sym from prices as p where p.price > 1;
Result
[
{ "b": 2, "c": 3 }
]
Pivot With
Pivot with order by is not supported in v1.
SQL
create table T;
create table prices;
pivot p.price at p.sym from prices as p order by p.sym;
Expected error: static
Unpivot
Unpivot Yields
Unpivot yields one binding per attribute-value pair, the value bound by AS.
SQL
create table T;
select price from unpivot {"amzn": 1900, "goog": 1120} as price;
Result
[
1900,
1120
]
AT Binds
AT binds the attribute name of each pair.
SQL
create table T;
select sym as sym, price as price from unpivot {"amzn": 1900, "goog": 1120} as price at sym;
Result
[
{ "sym": "amzn", "price": 1900 },
{ "sym": "goog", "price": 1120 }
]
Pairs Are
Pairs are produced in object member order.
SQL
create table T;
select sym as sym from unpivot {"c": 3, "a": 1, "b": 2} as price at sym;
Result
[
{ "sym": "c" },
{ "sym": "a" },
{ "sym": "b" }
]
AT May
AT may be omitted, binding only the value.
SQL
create table T;
select price from unpivot {"a": 10, "b": 20} as price;
Result
[
10,
20
]
Unpivot Dot Envelope
Select . envelopes the value and attribute bindings under their aliases.
SQL
create table T;
select . from unpivot {"a": 1, "b": 2} as v at k;
Result
[
{ "v": 1, "k": "a" },
{ "v": 2, "k": "b" }
]
Their Aliases
Select * spreads the scalar bindings under their aliases.
SQL
create table T;
select * from unpivot {"a": 1, "b": 2} as v at k;
Result
[
{ "v": 1, "k": "a" },
{ "v": 2, "k": "b" }
]
On Name
A where predicate may filter on the attribute name.
SQL
create table T;
select price from unpivot {"a": 1, "b": 2, "c": 3} as price at sym where sym != 'b';
Result
[
1,
3
]
Unpivot Of
Unpivot of a non-object value contributes no rows.
SQL
create table T;
select price from unpivot 5 as price at sym;
Result
[]
Unpivot Of
Unpivot of an empty object contributes no rows.
SQL
create table T;
select price from unpivot {} as price;
Result
[]
Unpivot A
Unpivot a table row's columns into (name, value) rows.
SQL
create table T;
create table closing;
insert into closing ({"date": "d1", "amzn": 1900, "goog": 1120});
select sym as sym, price as price from closing as c, unpivot c as price at sym where sym != 'date';
Result
[
{ "sym": "amzn", "price": 1900 },
{ "sym": "goog", "price": 1120 }
]
Unpivot Flattens
Unpivot flattens every outer row's members in order.
SQL
create table T;
create table P;
insert into P ({"a": 1, "b": 2}, {"a": 3, "b": 4});
select sym as k, price as v from P as p, unpivot p as price at sym;
Result
[
{ "k": "a", "v": 1 },
{ "k": "b", "v": 2 },
{ "k": "a", "v": 3 },
{ "k": "b", "v": 4 }
]
Order By
Order by sorts the unpivoted pairs by the attribute name.
SQL
create table T;
select price from unpivot {"b": 2, "a": 1, "c": 3} as price at sym order by sym;
Result
[
1,
2,
3
]
An Aggregate
An aggregate folds over the unpivoted value binding.
SQL
create table T;
select sum(price) from unpivot {"a": 10, "b": 20, "c": 30} as price;
Result
[
60
]
Count Over
Count over an unpivot source counts one row per pair.
SQL
create table T;
select count(price) from unpivot {"a": 1, "b": 2, "c": 3} as price;
Result
[
3
]
Group By
Group by over an unpivot source groups its value binding.
SQL
create table T;
select { "v": price, "n": count(*) } from unpivot {"a": 5, "b": 5, "c": 9} as price group by price;
Result
[
{ "v": 5, "n": 2 },
{ "v": 9, "n": 1 }
]
The Unpivot
The unpivot value binding requires an alias.
SQL
create table T;
select . from unpivot {"a": 1};
Expected error: static