Lösung 1. Einfache Abfrage mit einem Aggregat.
Der einfachste und schnellste Weg, um das erwartete Ergebnis zu erzielen. Es ist einfach, die sales
zu parsen Spalte innerhalb eines Client-Programms.
select item, string_agg(coalesce(sales, 0)::text, ',') sales
from (
select distinct item_id item, doy
from generate_series (1, 10) doy -- change 10 to given n
cross join entry_daily
) sub
left join entry_daily on item_id = item and day_of_year = doy
group by 1
order by 1;
item | sales
------+----------------------
A1 | 20,0,0,0,0,0,9,0,0,0
A2 | 11,0,0,0,0,0,0,0,0,0
(2 rows)
Lösung 2. Dynamisch erstellte Ansicht.
Basierend auf Lösung 1 mit array_agg()
statt string_agg()
. Die Funktion erstellt eine Ansicht mit einer bestimmten Anzahl von Spalten.
create or replace function create_items_view(view_name text, days int)
returns void language plpgsql as $$
declare
list text;
begin
select string_agg(format('s[%s] "%s"', i::text, i::text), ',')
into list
from generate_series(1, days) i;
execute(format($f$
drop view if exists %s;
create view %s as select item, %s
from (
select item, array_agg(coalesce(sales, 0)) s
from (
select distinct item_id item, doy
from generate_series (1, %s) doy
cross join entry_daily
) sub
left join entry_daily on item_id = item and day_of_year = doy
group by 1
order by 1
) q
$f$, view_name, view_name, list, days)
);
end $$;
Verwendung:
select create_items_view('items_view_10', 10);
select * from items_view_10;
item | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
------+----+---+---+---+---+---+---+---+---+----
A1 | 20 | 0 | 0 | 0 | 0 | 0 | 9 | 0 | 0 | 0
A2 | 11 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
(2 rows)
Lösung 3. Kreuztabelle.
Einfach zu bedienen, aber sehr unbequem mit der größeren Anzahl von Spalten, da das Zeilenformat definiert werden muss.
create extension if not exists tablefunc;
select * from crosstab (
'select item_id, day_of_year, sales
from entry_daily
order by 1',
'select i from generate_series (1, 10) i'
) as ct
(item_id text, "1" int, "2" int, "3" int, "4" int, "5" int, "6" int, "7" int, "8" int, "9" int, "10" int);
item_id | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
---------+----+---+---+---+---+---+---+---+---+----
A1 | 20 | | | | | | 9 | | |
A2 | 11 | | | | | | | | |
(2 rows)