z CTE nie jestem za dobry, więc jeśli poszalałem to niech mnie ktoś poprawi :)
to zwraca tylko unikalne nazwy produktów, tzn. jeśli w zakupy
jest kilka wpisów dla tego samego id_klient, id_produkt, dataokres, to nazwa produktu wyświetli się raz
jeśli chcesz żeby nazwa była tyle razy ile jest wpisów to użyj tej zakomentowanej części
with t0 (cid, dto, total) as
(
select client_id, dataokres, sum(price) from zakupy group by client_id, dataokres
),
t1 (cid, dto, zid, pname, x) as
(
select cid, dto, 0, cast('' as varchar(255)), 0 from t0
union all
select t1.cid, t1.dto, z.id, t1.pname || z.name ||',', t1.x+1
from t1,
(
/*
select z.id,z.client_id,z.dataokres,p.name from zakupy z
inner join produkty p on z.product_id = p.id
*/
select max(z.id) as id,z.client_id,z.dataokres,p.name from zakupy z
inner join produkty p on z.product_id = p.id
group by client_id,z.dataokres,p.name
) as z
where t1.zid < z.id and t1.cid = z.client_id and t1.dto = z.dataokres
)
select k.name, t0.dto, t0.total, t1.pname from t0
inner join (select cid, dto, max(zid) maxzid from t1 group by cid, dto) t1m on t0.cid=t1m.cid and t0.dto=t1m.dto
inner join (select cid, dto, max(x) maxx from t1 group by cid, dto) t1n on t0.cid=t1n.cid and t0.dto=t1n.dto
inner join t1 on t0.cid=t1.cid and t0.dto=t1.dto and t1m.maxzid=t1.zid and t1n.maxx=t1.x
inner join klienci k on t0.cid=k.id
tzn. da się to zrobić prościej używając funkcji rankingujących, ale ja mam pod ręką tylko stare db2 gdzie tego nie ma :/
bez testów to powinno mniej więcej być tak
with t1 (nr, cid, dto, total, pname) as
(
select row_number() over (partition by z.client_id, z.dataokres order by ),
z.client_id, z.dataokres, sum(z.price) as price, p.name
from zakupy z
inner join produkty p on p.id=z.product_id
group by z.client_id, z.dataokres, z.product_id, p.name
)
t2 (nr, cid, dto, total, pname) as
(
select * from t1 where nr = 1
union all
select t1.nr, t2.cid, t2.dto, t2.total, t2.pname || ',' || t1.pname
from t1,t2
where t2.nr + 1 = t1.nr and t1.cid=t2.cid and t1.dto=t2.dto
)
select k.name, t2.dto, t2.total, t2.pname from t2
inner join (select cid, dto, max(nr) as maxnr from t2 group by cid, dto) as x on x.cid=t2.cid and x.dto=t2.dto and x.maxnr=t2.nr
inner join klienci k on t2.cid=k.id
W sql serverze można jeszcze użyć mechanizmów związanych z xml aby dokonać konkatenacji stringów, ale średnio pamiętam jak, więc z głowy nie chce bzdur pisać. Niemniej używałem tego kilka razy i działało bez zarzutów.
W linq teraz ci nie powiem, bo nie mam jak przetestować.