2

Given this table:

SELECT * FROM CommodityPricing order by dateField

"SILVER";60.45;"2002-01-01"
"GOLD";130.45;"2002-01-01"
"COPPER";96.45;"2002-01-01"
"SILVER";70.45;"2003-01-01"
"GOLD";140.45;"2003-01-01"
"COPPER";99.45;"2003-01-01"
"GOLD";150.45;"2004-01-01"
"MERCURY";60;"2004-01-01"
"SILVER";80.45;"2004-01-01"

As of 2004, COPPER was dropped and mercury introduced.
How can I get the value of (array_agg(value order by date desc) ) [1] as NULL for COPPER?

select commodity,(array_agg(value order by date desc) ) --[1]
from CommodityPricing
group by commodity

"COPPER";"{99.45,96.45}"
"GOLD";"{150.45,140.45,130.45}"
"MERCURY";"{60}"
"SILVER";"{80.45,70.45,60.45}"
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
byomjan
  • 119
  • 1
  • 8

2 Answers2

0

SQL Fiddle

select
    commodity,
    array_agg(
        case when commodity = 'COPPER' then null else price end
        order by date desc
    )
from CommodityPricing
group by commodity
;
Clodoaldo Neto
  • 118,695
  • 26
  • 233
  • 260
0

To "pad" missing rows with null values in the resulting array, build your query on a full grid of rows and LEFT JOIN to actual values to the grid.

Given this table definition:

CREATE TABLE price (
  commodity text
, value     numeric
, ts        timestamp  -- using ts instead of the inappropriate name date 
);

Use generate_series() to get a list of timestamps representing the years and CROSS JOIN to a unique list of all commodities (SELECT DISTINCT ...).

SELECT commodity, array_agg(value ORDER BY ts DESC) AS years
FROM   generate_series (timestamp '2002-01-01'
                      , timestamp '2004-01-01'
                      , '1 year') t(ts)
CROSS  JOIN (SELECT DISTINCT commodity FROM price) c(commodity)
LEFT   JOIN price p USING (ts, commodity)
GROUP  BY commodity;

Result:

commodity years
COPPER {NULL,99.45,96.45}
GOLD {150.45,140.45,130.45}
MERCURY {60,NULL,NULL}
SILVER {80.45,70.45,60.45}

fiddle
Old sqlfiddle

Related:

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228